Repository: square/retrofit
Issue: UrlFetchClient: missing Content-Type

UrlFetchClient doesn't set the Content-Type from the body, but only relies from request's headers.

Quick Fix:

```
    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) {

            /*----> Set Content-Type from body <---- */
            if(body.mimeType() != null)
                fetchRequest.addHeader(new HTTPHeader("Content-Type", body.mimeType()));

            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            body.writeTo(baos);
            fetchRequest.setPayload(baos.toByteArray());
        }

        return fetchRequest;
    }
```


Issue comments:

Pull request review comments:

Patch that resolved the issue:
diff --git a/retrofit/src/main/java/retrofit/appengine/UrlFetchClient.java b/retrofit/src/main/java/retrofit/appengine/UrlFetchClient.java
index 5bc2298615..4c6c49716c 100644
--- a/retrofit/src/main/java/retrofit/appengine/UrlFetchClient.java
+++ b/retrofit/src/main/java/retrofit/appengine/UrlFetchClient.java
@@ -51,7 +51,7 @@ public UrlFetchClient(URLFetchService urlFetchService) {
   @Override public Response execute(Request request) throws IOException {
     HTTPRequest fetchRequest = createRequest(request);
     HTTPResponse fetchResponse = execute(urlFetchService, fetchRequest);
-    return parseResponse(fetchResponse);
+    return parseResponse(fetchResponse, fetchRequest);
   }
 
   /** Execute the specified {@code request} using the provided {@code urlFetchService}. */
@@ -79,8 +79,11 @@ static HTTPRequest createRequest(Request request) throws IOException {
     return fetchRequest;
   }
 
-  static Response parseResponse(HTTPResponse response) {
-    String url = response.getFinalUrl().toString();
+  static Response parseResponse(HTTPResponse response, HTTPRequest creatingRequest) {
+    // Response URL will be null if it is the same as the request URL.
+    URL responseUrl = response.getFinalUrl();
+    String urlString = (responseUrl != null ? responseUrl : creatingRequest.getURL()).toString();
+
     int status = response.getResponseCode();
 
     List<HTTPHeader> fetchHeaders = response.getHeaders();
@@ -101,6 +104,6 @@ static Response parseResponse(HTTPResponse response) {
       body = new TypedByteArray(contentType, fetchBody);
     }
 
-    return new Response(url, status, "", headers, body);
+    return new Response(urlString, status, "", headers, body);
   }
 }


Test patch:
diff --git a/retrofit/src/test/java/retrofit/appengine/UrlFetchClientTest.java b/retrofit/src/test/java/retrofit/appengine/UrlFetchClientTest.java
index 35455fb651..212b9d1290 100644
--- a/retrofit/src/test/java/retrofit/appengine/UrlFetchClientTest.java
+++ b/retrofit/src/test/java/retrofit/appengine/UrlFetchClientTest.java
@@ -24,6 +24,7 @@
 import static java.util.Arrays.asList;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
 import static org.mockito.Mockito.when;
 import static retrofit.TestingUtils.assertBytes;
 
@@ -81,6 +82,8 @@ public class UrlFetchClientTest {
   }
 
   @Test public void response() throws Exception {
+    HTTPRequest creatingRequest = mock(HTTPRequest.class);
+
     HTTPResponse fetchResponse = mock(HTTPResponse.class);
     when(fetchResponse.getHeaders()).thenReturn(
         asList(new HTTPHeader("foo", "bar"), new HTTPHeader("kit", "kat"),
@@ -89,7 +92,32 @@ public class UrlFetchClientTest {
     when(fetchResponse.getFinalUrl()).thenReturn(new URL(HOST + "/foo/bar/"));
     when(fetchResponse.getResponseCode()).thenReturn(200);
 
-    Response response = UrlFetchClient.parseResponse(fetchResponse);
+    Response response = UrlFetchClient.parseResponse(fetchResponse, creatingRequest);
+
+    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");
+
+    verifyNoMoreInteractions(creatingRequest);
+  }
+
+  @Test public void responseNullUrlPullsFromRequest() throws Exception {
+    HTTPRequest creatingRequest = mock(HTTPRequest.class);
+    when(creatingRequest.getURL()).thenReturn(new URL(HOST + "/foo/bar/"));
+
+    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(null);
+    when(fetchResponse.getResponseCode()).thenReturn(200);
+
+    Response response = UrlFetchClient.parseResponse(fetchResponse, creatingRequest);
 
     assertThat(response.getUrl()).isEqualTo(HOST + "/foo/bar/");
     assertThat(response.getStatus()).isEqualTo(200);
@@ -101,6 +129,8 @@ public class UrlFetchClientTest {
   }
 
   @Test public void emptyResponse() throws Exception {
+    HTTPRequest creatingRequest = mock(HTTPRequest.class);
+
     HTTPResponse fetchResponse = mock(HTTPResponse.class);
     when(fetchResponse.getHeaders()).thenReturn(
         asList(new HTTPHeader("foo", "bar"), new HTTPHeader("kit", "kat")));
@@ -108,7 +138,7 @@ public class UrlFetchClientTest {
     when(fetchResponse.getFinalUrl()).thenReturn(new URL(HOST + "/foo/bar/"));
     when(fetchResponse.getResponseCode()).thenReturn(200);
 
-    Response response = UrlFetchClient.parseResponse(fetchResponse);
+    Response response = UrlFetchClient.parseResponse(fetchResponse, creatingRequest);
 
     assertThat(response.getUrl()).isEqualTo(HOST + "/foo/bar/");
     assertThat(response.getStatus()).isEqualTo(200);
@@ -116,6 +146,8 @@ public class UrlFetchClientTest {
     assertThat(response.getHeaders()).hasSize(2) //
         .containsExactly(new Header("foo", "bar"), new Header("kit", "kat"));
     assertThat(response.getBody()).isNull();
+
+    verifyNoMoreInteractions(creatingRequest);
   }
 
   private static void assertHeader(HTTPHeader header, String name, String value) {