forked from square/retrofit
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for AppEngine's URLFetchService.
- Loading branch information
1 parent
883a7c9
commit 449cfaa
Showing
7 changed files
with
295 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
112 changes: 112 additions & 0 deletions
112
retrofit/src/main/java/retrofit/appengine/UrlFetchClient.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
package retrofit.appengine; | ||
|
||
import com.google.appengine.api.urlfetch.HTTPHeader; | ||
import com.google.appengine.api.urlfetch.HTTPMethod; | ||
import com.google.appengine.api.urlfetch.HTTPRequest; | ||
import com.google.appengine.api.urlfetch.HTTPResponse; | ||
import com.google.appengine.api.urlfetch.URLFetchService; | ||
import com.google.appengine.api.urlfetch.URLFetchServiceFactory; | ||
import java.io.ByteArrayOutputStream; | ||
import java.io.IOException; | ||
import java.net.URL; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
import retrofit.client.Client; | ||
import retrofit.client.Header; | ||
import retrofit.client.Request; | ||
import retrofit.client.Response; | ||
import retrofit.mime.TypedByteArray; | ||
import retrofit.mime.TypedOutput; | ||
|
||
/** A {@link Client} for Google AppEngine's which uses its {@link URLFetchService}. */ | ||
public class UrlFetchClient implements Client { | ||
private static HTTPMethod getHttpMethod(String method) { | ||
if ("GET".equals(method)) { | ||
return HTTPMethod.GET; | ||
} else if ("POST".equals(method)) { | ||
return HTTPMethod.POST; | ||
} else if ("PATCH".equals(method)) { | ||
return HTTPMethod.PATCH; | ||
} else if ("PUT".equals(method)) { | ||
return HTTPMethod.PUT; | ||
} else if ("DELETE".equals(method)) { | ||
return HTTPMethod.DELETE; | ||
} else if ("HEAD".equals(method)) { | ||
return HTTPMethod.HEAD; | ||
} else { | ||
throw new IllegalStateException("Illegal HTTP method: " + method); | ||
} | ||
} | ||
|
||
private final URLFetchService urlFetchService; | ||
|
||
public UrlFetchClient() { | ||
this(URLFetchServiceFactory.getURLFetchService()); | ||
} | ||
|
||
public UrlFetchClient(URLFetchService urlFetchService) { | ||
this.urlFetchService = urlFetchService; | ||
} | ||
|
||
@Override public Response execute(Request request) throws IOException { | ||
HTTPRequest fetchRequest = createRequest(request); | ||
HTTPResponse fetchResponse = execute(urlFetchService, fetchRequest); | ||
return parseResponse(fetchResponse); | ||
} | ||
|
||
/** Execute the specified {@code request} using the provided {@code urlFetchService}. */ | ||
protected HTTPResponse execute(URLFetchService urlFetchService, HTTPRequest request) | ||
throws IOException { | ||
return urlFetchService.fetch(request); | ||
} | ||
|
||
static HTTPRequest createRequest(Request request) throws IOException { | ||
HTTPMethod httpMethod = getHttpMethod(request.getMethod()); | ||
URL url = new URL(request.getUrl()); | ||
HTTPRequest fetchRequest = new HTTPRequest(url, httpMethod); | ||
|
||
for (Header header : request.getHeaders()) { | ||
fetchRequest.addHeader(new HTTPHeader(header.getName(), header.getValue())); | ||
} | ||
|
||
TypedOutput body = request.getBody(); | ||
if (body != null) { | ||
fetchRequest.setHeader(new HTTPHeader("Content-Type", body.mimeType())); | ||
long length = body.length(); | ||
if (length != -1) { | ||
fetchRequest.setHeader(new HTTPHeader("Content-Length", String.valueOf(length))); | ||
} | ||
|
||
ByteArrayOutputStream baos = new ByteArrayOutputStream(); | ||
body.writeTo(baos); | ||
fetchRequest.setPayload(baos.toByteArray()); | ||
} | ||
|
||
return fetchRequest; | ||
} | ||
|
||
static Response parseResponse(HTTPResponse response) { | ||
String url = response.getFinalUrl().toString(); | ||
int status = response.getResponseCode(); | ||
|
||
List<HTTPHeader> fetchHeaders = response.getHeaders(); | ||
List<Header> headers = new ArrayList<Header>(fetchHeaders.size()); | ||
String contentType = "application/octet-stream"; | ||
for (HTTPHeader fetchHeader : fetchHeaders) { | ||
String name = fetchHeader.getName(); | ||
String value = fetchHeader.getValue(); | ||
if ("Content-Type".equalsIgnoreCase(name)) { | ||
contentType = value; | ||
} | ||
headers.add(new Header(name, value)); | ||
} | ||
|
||
TypedByteArray body = null; | ||
byte[] fetchBody = response.getContent(); | ||
if (fetchBody != null) { | ||
body = new TypedByteArray(contentType, fetchBody); | ||
} | ||
|
||
return new Response(url, status, "", headers, body); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
131 changes: 131 additions & 0 deletions
131
retrofit/src/test/java/retrofit/appengine/UrlFetchClientTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
// Copyright 2014 Square, Inc. | ||
package retrofit.appengine; | ||
|
||
import com.google.appengine.api.urlfetch.HTTPHeader; | ||
import com.google.appengine.api.urlfetch.HTTPRequest; | ||
import com.google.appengine.api.urlfetch.HTTPResponse; | ||
import com.google.common.io.ByteStreams; | ||
import java.io.IOException; | ||
import java.net.URL; | ||
import java.util.ArrayList; | ||
import java.util.LinkedHashMap; | ||
import java.util.List; | ||
import java.util.Map; | ||
import org.junit.Test; | ||
import retrofit.TestingUtils; | ||
import retrofit.client.Header; | ||
import retrofit.client.Request; | ||
import retrofit.client.Response; | ||
import retrofit.mime.TypedOutput; | ||
import retrofit.mime.TypedString; | ||
|
||
import static com.google.appengine.api.urlfetch.HTTPMethod.GET; | ||
import static com.google.appengine.api.urlfetch.HTTPMethod.POST; | ||
import static java.util.Arrays.asList; | ||
import static org.fest.assertions.api.Assertions.assertThat; | ||
import static org.mockito.Mockito.mock; | ||
import static org.mockito.Mockito.when; | ||
import static retrofit.TestingUtils.assertBytes; | ||
|
||
public class UrlFetchClientTest { | ||
private static final String HOST = "http://example.com"; | ||
|
||
@Test public void get() throws IOException { | ||
Request request = new Request("GET", HOST + "/foo/bar/?kit=kat", null, null); | ||
HTTPRequest fetchRequest = UrlFetchClient.createRequest(request); | ||
|
||
assertThat(fetchRequest.getMethod()).isEqualTo(GET); | ||
assertThat(fetchRequest.getURL().toString()).isEqualTo(HOST + "/foo/bar/?kit=kat"); | ||
assertThat(fetchRequest.getHeaders()).isEmpty(); | ||
assertThat(fetchRequest.getPayload()).isNull(); | ||
} | ||
|
||
@Test public void post() throws IOException { | ||
TypedString body = new TypedString("hi"); | ||
Request request = new Request("POST", HOST + "/foo/bar/", null, body); | ||
HTTPRequest fetchRequest = UrlFetchClient.createRequest(request); | ||
|
||
assertThat(fetchRequest.getMethod()).isEqualTo(POST); | ||
assertThat(fetchRequest.getURL().toString()).isEqualTo(HOST + "/foo/bar/"); | ||
List<HTTPHeader> fetchHeaders = fetchRequest.getHeaders(); | ||
assertThat(fetchHeaders).hasSize(2); | ||
assertHeader(fetchHeaders.get(0), "Content-Type", "text/plain; charset=UTF-8"); | ||
assertHeader(fetchHeaders.get(1), "Content-Length", "2"); | ||
assertBytes(fetchRequest.getPayload(), "hi"); | ||
} | ||
|
||
@Test public void multipart() throws IOException { | ||
Map<String, TypedOutput> bodyParams = new LinkedHashMap<String, TypedOutput>(); | ||
bodyParams.put("foo", new TypedString("bar")); | ||
bodyParams.put("ping", new TypedString("pong")); | ||
TypedOutput body = TestingUtils.createMultipart(bodyParams); | ||
Request request = new Request("POST", HOST + "/that/", null, body); | ||
HTTPRequest fetchRequest = UrlFetchClient.createRequest(request); | ||
|
||
assertThat(fetchRequest.getMethod()).isEqualTo(POST); | ||
assertThat(fetchRequest.getURL().toString()).isEqualTo(HOST + "/that/"); | ||
List<HTTPHeader> fetchHeaders = fetchRequest.getHeaders(); | ||
assertThat(fetchHeaders).hasSize(2); | ||
HTTPHeader headerZero = fetchHeaders.get(0); | ||
assertThat(headerZero.getName()).isEqualTo("Content-Type"); | ||
assertThat(headerZero.getValue()).startsWith("multipart/form-data; boundary="); | ||
assertHeader(fetchHeaders.get(1), "Content-Length", String.valueOf(body.length())); | ||
assertThat(fetchRequest.getPayload()).isNotEmpty(); | ||
} | ||
|
||
@Test public void headers() throws IOException { | ||
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); | ||
HTTPRequest fetchRequest = UrlFetchClient.createRequest(request); | ||
|
||
List<HTTPHeader> fetchHeaders = fetchRequest.getHeaders(); | ||
assertThat(fetchHeaders).hasSize(2); | ||
assertHeader(fetchHeaders.get(0), "kit", "kat"); | ||
assertHeader(fetchHeaders.get(1), "foo", "bar"); | ||
} | ||
|
||
@Test public void response() throws Exception { | ||
HTTPResponse fetchResponse = mock(HTTPResponse.class); | ||
when(fetchResponse.getHeaders()).thenReturn( | ||
asList(new HTTPHeader("foo", "bar"), new HTTPHeader("kit", "kat"), | ||
new HTTPHeader("Content-Type", "text/plain"))); | ||
when(fetchResponse.getContent()).thenReturn("hello".getBytes("UTF-8")); | ||
when(fetchResponse.getFinalUrl()).thenReturn(new URL(HOST + "/foo/bar/")); | ||
when(fetchResponse.getResponseCode()).thenReturn(200); | ||
|
||
Response response = UrlFetchClient.parseResponse(fetchResponse); | ||
|
||
assertThat(response.getUrl()).isEqualTo(HOST + "/foo/bar/"); | ||
assertThat(response.getStatus()).isEqualTo(200); | ||
assertThat(response.getReason()).isEqualTo(""); | ||
assertThat(response.getHeaders()).hasSize(3) // | ||
.containsOnly(new Header("foo", "bar"), new Header("kit", "kat"), | ||
new Header("Content-Type", "text/plain")); | ||
assertBytes(ByteStreams.toByteArray(response.getBody().in()), "hello"); | ||
} | ||
|
||
@Test public void emptyResponse() throws Exception { | ||
HTTPResponse fetchResponse = mock(HTTPResponse.class); | ||
when(fetchResponse.getHeaders()).thenReturn( | ||
asList(new HTTPHeader("foo", "bar"), new HTTPHeader("kit", "kat"))); | ||
when(fetchResponse.getContent()).thenReturn(null); | ||
when(fetchResponse.getFinalUrl()).thenReturn(new URL(HOST + "/foo/bar/")); | ||
when(fetchResponse.getResponseCode()).thenReturn(200); | ||
|
||
Response response = UrlFetchClient.parseResponse(fetchResponse); | ||
|
||
assertThat(response.getUrl()).isEqualTo(HOST + "/foo/bar/"); | ||
assertThat(response.getStatus()).isEqualTo(200); | ||
assertThat(response.getReason()).isEqualTo(""); | ||
assertThat(response.getHeaders()).hasSize(2) // | ||
.containsExactly(new Header("foo", "bar"), new Header("kit", "kat")); | ||
assertThat(response.getBody()).isNull(); | ||
} | ||
|
||
private static void assertHeader(HTTPHeader header, String name, String value) { | ||
assertThat(header.getName()).isEqualTo(name); | ||
assertThat(header.getValue()).isEqualTo(value); | ||
} | ||
} |
Oops, something went wrong.