Skip to content

Commit

Permalink
Update to native OkHttp 2.0 APIs.
Browse files Browse the repository at this point in the history
  • Loading branch information
JakeWharton committed Dec 30, 2014
1 parent ed1122a commit a047a59
Show file tree
Hide file tree
Showing 5 changed files with 207 additions and 39 deletions.
5 changes: 0 additions & 5 deletions pom.xml
Expand Up @@ -104,11 +104,6 @@
<artifactId>okhttp</artifactId>
<version>${okhttp.version}</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp</groupId>
<artifactId>okhttp-urlconnection</artifactId>
<version>${okhttp.version}</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
Expand Down
5 changes: 0 additions & 5 deletions retrofit/pom.xml
Expand Up @@ -29,11 +29,6 @@
<artifactId>okhttp</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.squareup.okhttp</groupId>
<artifactId>okhttp-urlconnection</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>io.reactivex</groupId>
<artifactId>rxjava</artifactId>
Expand Down
24 changes: 3 additions & 21 deletions retrofit/src/main/java/retrofit/Platform.java
Expand Up @@ -139,30 +139,12 @@ private static class Android extends Platform {

/** Determine whether or not OkHttp 1.6 or newer is present on the runtime classpath. */
private static boolean hasOkHttpOnClasspath() {
boolean okUrlFactory = false;
try {
Class.forName("com.squareup.okhttp.OkUrlFactory");
okUrlFactory = true;
} catch (ClassNotFoundException e) {
}

boolean okHttpClient = false;
try {
Class.forName("com.squareup.okhttp.OkHttpClient");
okHttpClient = true;
} catch (ClassNotFoundException e) {
}

if (okHttpClient != okUrlFactory) {
throw new RuntimeException(""
+ "Retrofit detected an unsupported OkHttp on the classpath.\n"
+ "To use OkHttp with this version of Retrofit, you'll need:\n"
+ "1. com.squareup.okhttp:okhttp:1.6.0 (or newer)\n"
+ "2. com.squareup.okhttp:okhttp-urlconnection:1.6.0 (or newer)\n"
+ "Note that OkHttp 2.0.0+ is supported!");
return true;
} catch (ClassNotFoundException ignored) {
}

return okHttpClient;
return false;
}

/**
Expand Down
91 changes: 83 additions & 8 deletions retrofit/src/main/java/retrofit/client/OkClient.java
Expand Up @@ -15,33 +15,108 @@
*/
package retrofit.client;

import com.squareup.okhttp.Headers;
import com.squareup.okhttp.MediaType;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.OkUrlFactory;
import com.squareup.okhttp.RequestBody;
import com.squareup.okhttp.ResponseBody;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import okio.BufferedSink;
import retrofit.mime.TypedInput;
import retrofit.mime.TypedOutput;

/** Retrofit client that uses OkHttp for communication. */
public class OkClient extends UrlConnectionClient {
public class OkClient implements Client {
private static OkHttpClient generateDefaultOkHttp() {
OkHttpClient client = new OkHttpClient();
client.setConnectTimeout(Defaults.CONNECT_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
client.setReadTimeout(Defaults.READ_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
return client;
}

private final OkUrlFactory okUrlFactory;
private final OkHttpClient client;

public OkClient() {
this(generateDefaultOkHttp());
}

public OkClient(OkHttpClient client) {
this.okUrlFactory = new OkUrlFactory(client);
if (client == null) throw new NullPointerException("client");
this.client = client;
}

@Override protected HttpURLConnection openConnection(Request request) throws IOException {
return okUrlFactory.open(new URL(request.getUrl()));
@Override public Response execute(Request request) throws IOException {
return parseResponse(client.newCall(createRequest(request)).execute());
}

static com.squareup.okhttp.Request createRequest(Request request) {
com.squareup.okhttp.Request.Builder builder = new com.squareup.okhttp.Request.Builder()
.url(request.getUrl())
.method(request.getMethod(), createRequestBody(request.getBody()));

List<Header> headers = request.getHeaders();
for (int i = 0, size = headers.size(); i < size; i++) {
Header header = headers.get(i);
builder.addHeader(header.getName(), header.getValue());
}

return builder.build();
}

static Response parseResponse(com.squareup.okhttp.Response response) {
return new Response(response.request().urlString(), response.code(), response.message(),
createHeaders(response.headers()), createResponseBody(response.body()));
}

private static RequestBody createRequestBody(final TypedOutput body) {
if (body == null) {
return null;
}
final MediaType mediaType = MediaType.parse(body.mimeType());
return new RequestBody() {
@Override public MediaType contentType() {
return mediaType;
}

@Override public void writeTo(BufferedSink sink) throws IOException {
body.writeTo(sink.outputStream());
}

@Override public long contentLength() {
return body.length();
}
};
}

private static TypedInput createResponseBody(final ResponseBody body) {
if (body == null) {
return null;
}
return new TypedInput() {
@Override public String mimeType() {
return body.contentType().toString();
}

@Override public long length() {
return body.contentLength();
}

@Override public InputStream in() throws IOException {
return body.byteStream();
}
};
}

private static List<Header> createHeaders(Headers headers) {
int size = headers.size();
List<Header> headerList = new ArrayList<Header>(size);
for (int i = 0; i < size; i++) {
headerList.add(new Header(headers.name(i), headers.value(i)));
}
return headerList;
}
}
121 changes: 121 additions & 0 deletions retrofit/src/test/java/retrofit/client/OkClientTest.java
@@ -0,0 +1,121 @@
package retrofit.client;

import com.google.common.io.ByteStreams;
import com.squareup.okhttp.Headers;
import com.squareup.okhttp.MediaType;
import com.squareup.okhttp.Protocol;
import com.squareup.okhttp.RequestBody;
import com.squareup.okhttp.ResponseBody;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import okio.Buffer;
import okio.BufferedSource;
import org.junit.Test;
import retrofit.mime.TypedInput;
import retrofit.mime.TypedString;

import static org.assertj.core.api.Assertions.assertThat;
import static retrofit.TestingUtils.assertBytes;

public final class OkClientTest {
private static final String HOST = "http://example.com";

@Test public void get() {
Request request = new Request("GET", HOST + "/foo/bar/?kit=kat", null, null);
com.squareup.okhttp.Request okRequest = OkClient.createRequest(request);

assertThat(okRequest.method()).isEqualTo("GET");
assertThat(okRequest.urlString()).isEqualTo(HOST + "/foo/bar/?kit=kat");
assertThat(okRequest.headers().size()).isEqualTo(0);
assertThat(okRequest.body()).isNull();
}

@Test public void post() throws IOException {
TypedString body = new TypedString("hi");
Request request = new Request("POST", HOST + "/foo/bar/", null, body);
com.squareup.okhttp.Request okRequest = OkClient.createRequest(request);

assertThat(okRequest.method()).isEqualTo("POST");
assertThat(okRequest.urlString()).isEqualTo(HOST + "/foo/bar/");
assertThat(okRequest.headers().size()).isEqualTo(0);

RequestBody okBody = okRequest.body();
assertThat(okBody).isNotNull();

Buffer buffer = new Buffer();
okBody.writeTo(buffer);
assertThat(buffer.readUtf8()).isEqualTo("hi");
}

@Test public void headers() {
List<Header> headers = new ArrayList<Header>();
headers.add(new Header("kit", "kat"));
headers.add(new Header("foo", "bar"));
Request request = new Request("GET", HOST + "/this/", headers, null);
com.squareup.okhttp.Request okRequest = OkClient.createRequest(request);

Headers okHeaders = okRequest.headers();
assertThat(okHeaders.size()).isEqualTo(2);
assertThat(okHeaders.get("kit")).isEqualTo("kat");
assertThat(okHeaders.get("foo")).isEqualTo("bar");
}

@Test public void response() throws IOException {
ResponseBody body = new ResponseBody() {
@Override public MediaType contentType() {
return MediaType.parse("text/plain");
}

@Override public long contentLength() {
return 5;
}

@Override public BufferedSource source() {
return new Buffer().writeUtf8("hello");
}
};
com.squareup.okhttp.Response okResponse = new com.squareup.okhttp.Response.Builder()
.code(200).message("OK")
.body(body)
.addHeader("foo", "bar")
.addHeader("kit", "kat")
.protocol(Protocol.HTTP_1_1)
.request(new com.squareup.okhttp.Request.Builder()
.url(HOST + "/foo/bar/")
.get()
.build())
.build();
Response response = OkClient.parseResponse(okResponse);

assertThat(response.getUrl()).isEqualTo(HOST + "/foo/bar/");
assertThat(response.getStatus()).isEqualTo(200);
assertThat(response.getReason()).isEqualTo("OK");
assertThat(response.getHeaders()).hasSize(2) //
.containsOnly(new Header("foo", "bar"), new Header("kit", "kat"));
TypedInput responseBody = response.getBody();
assertThat(responseBody.mimeType()).isEqualTo("text/plain");
assertBytes(ByteStreams.toByteArray(responseBody.in()), "hello");
}

@Test public void emptyResponse() throws IOException {
com.squareup.okhttp.Response okResponse = new com.squareup.okhttp.Response.Builder()
.code(200).message("OK")
.addHeader("foo", "bar")
.addHeader("kit", "kat")
.protocol(Protocol.HTTP_1_1)
.request(new com.squareup.okhttp.Request.Builder()
.url(HOST + "/foo/bar/")
.get()
.build())
.build();
Response response = OkClient.parseResponse(okResponse);

assertThat(response.getUrl()).isEqualTo(HOST + "/foo/bar/");
assertThat(response.getStatus()).isEqualTo(200);
assertThat(response.getReason()).isEqualTo("OK");
assertThat(response.getHeaders()).hasSize(2) //
.containsExactly(new Header("foo", "bar"), new Header("kit", "kat"));
assertThat(response.getBody()).isNull();
}
}

0 comments on commit a047a59

Please sign in to comment.