From 8035fda72fd7c582d2f1b7df52fdae90d3959909 Mon Sep 17 00:00:00 2001 From: Kristopher Wuollett Date: Thu, 11 Jul 2013 22:46:30 -0700 Subject: [PATCH] Added contentType/Encoding to HttpResponse's Entity. Clients should expect that OkHttpClient HttpResponse Entity's contentType and contentEncoding are not null when the headers are present. --- .../okhttp/apache/OkApacheClient.java | 21 ++- .../okhttp/apache/OkApacheClientTest.java | 140 ++++++++++++++++++ 2 files changed, 154 insertions(+), 7 deletions(-) diff --git a/okhttp-apache/src/main/java/com/squareup/okhttp/apache/OkApacheClient.java b/okhttp-apache/src/main/java/com/squareup/okhttp/apache/OkApacheClient.java index 57b11147249a..2c40f9aa8c6d 100644 --- a/okhttp-apache/src/main/java/com/squareup/okhttp/apache/OkApacheClient.java +++ b/okhttp-apache/src/main/java/com/squareup/okhttp/apache/OkApacheClient.java @@ -21,6 +21,7 @@ import org.apache.http.conn.ClientConnectionManager; import org.apache.http.conn.params.ConnRouteParams; import org.apache.http.entity.InputStreamEntity; +import org.apache.http.message.BasicHeader; import org.apache.http.message.BasicHttpResponse; import org.apache.http.params.AbstractHttpParams; import org.apache.http.params.HttpParams; @@ -152,19 +153,25 @@ protected HttpURLConnection openConnection(URL url) { int responseCode = connection.getResponseCode(); String message = connection.getResponseMessage(); BasicHttpResponse response = new BasicHttpResponse(HTTP_1_1, responseCode, message); + // Get the response body ready to stream. + InputStream responseBody = + responseCode < HttpURLConnection.HTTP_BAD_REQUEST ? connection.getInputStream() + : connection.getErrorStream(); + InputStreamEntity entity = new InputStreamEntity(responseBody, connection.getContentLength()); for (int i = 0; true; i++) { String name = connection.getHeaderFieldKey(i); if (name == null) { break; } - response.addHeader(name, connection.getHeaderField(i)); + BasicHeader header = new BasicHeader(name, connection.getHeaderField(i)); + response.addHeader(header); + if (name.equalsIgnoreCase("Content-Type")) { + entity.setContentType(header); + } else if (name.equalsIgnoreCase("Content-Encoding")) { + entity.setContentEncoding(header); + } } - - // Get the response body ready to stream. - InputStream responseBody = - responseCode < HttpURLConnection.HTTP_BAD_REQUEST ? connection.getInputStream() - : connection.getErrorStream(); - response.setEntity(new InputStreamEntity(responseBody, connection.getContentLength())); + response.setEntity(entity); return response; } diff --git a/okhttp-apache/src/test/java/com/squareup/okhttp/apache/OkApacheClientTest.java b/okhttp-apache/src/test/java/com/squareup/okhttp/apache/OkApacheClientTest.java index bae6983a3f6f..22543c34ff87 100644 --- a/okhttp-apache/src/test/java/com/squareup/okhttp/apache/OkApacheClientTest.java +++ b/okhttp-apache/src/test/java/com/squareup/okhttp/apache/OkApacheClientTest.java @@ -4,8 +4,14 @@ import com.google.mockwebserver.MockWebServer; import com.google.mockwebserver.RecordedRequest; import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStreamWriter; +import java.nio.charset.Charset; import java.util.Arrays; +import java.util.zip.GZIPInputStream; +import java.util.zip.GZIPOutputStream; import org.apache.http.Header; import org.apache.http.HttpResponse; import org.apache.http.client.methods.HttpGet; @@ -18,6 +24,8 @@ import org.junit.Test; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; public class OkApacheClientTest { @@ -111,4 +119,136 @@ public class OkApacheClientTest { assertTrue(Arrays.equals(body, request.getBody())); assertEquals(request.getHeader("Content-Length"), "13"); } + + @Test public void contentType() throws Exception { + server.enqueue(new MockResponse().setBody("

Hello, World!

") + .setHeader("Content-Type", "text/html")); + server.enqueue(new MockResponse().setBody("{\"Message\": { \"text\": \"Hello, World!\" } }") + .setHeader("Content-Type", "application/json")); + server.enqueue(new MockResponse().setBody("Hello, World!")); + + HttpGet request1 = new HttpGet(server.getUrl("/").toURI()); + HttpResponse response1 = client.execute(request1); + Header[] headers1 = response1.getHeaders("Content-Type"); + assertEquals(1, headers1.length); + assertEquals("text/html", headers1[0].getValue()); + assertNotNull(response1.getEntity().getContentType()); + assertEquals("text/html", response1.getEntity().getContentType().getValue()); + + HttpGet request2 = new HttpGet(server.getUrl("/").toURI()); + HttpResponse response2 = client.execute(request2); + Header[] headers2 = response2.getHeaders("Content-Type"); + assertEquals(1, headers2.length); + assertEquals("application/json", headers2[0].getValue()); + assertNotNull(response2.getEntity().getContentType()); + assertEquals("application/json", response2.getEntity().getContentType().getValue()); + + HttpGet request3 = new HttpGet(server.getUrl("/").toURI()); + HttpResponse response3 = client.execute(request3); + Header[] headers3 = response3.getHeaders("Content-Type"); + assertEquals(0, headers3.length); + assertNull(response3.getEntity().getContentType()); + } + + @Test public void contentEncoding() throws Exception { + String text = "{\"Message\": { \"text\": \"Hello, World!\" } }"; + ByteArrayOutputStream bodyBytes = new ByteArrayOutputStream(); + OutputStreamWriter body = new OutputStreamWriter(new GZIPOutputStream(bodyBytes), + Charset.forName("UTF-8")); + body.write(text); + body.close(); + server.enqueue(new MockResponse().setBody(bodyBytes.toByteArray()) + .setHeader("Content-Encoding", "gzip")); + + byte[] tmp = new byte[32]; + + HttpGet request1 = new HttpGet(server.getUrl("/").toURI()); + request1.setHeader("Accept-encoding", "gzip"); // not transparent gzip + HttpResponse response1 = client.execute(request1); + Header[] headers1 = response1.getHeaders("Content-Encoding"); + assertEquals(1, headers1.length); + assertEquals("gzip", headers1[0].getValue()); + assertNotNull(response1.getEntity().getContentEncoding()); + assertEquals("gzip", response1.getEntity().getContentEncoding().getValue()); + InputStream content = new GZIPInputStream(response1.getEntity().getContent()); + ByteArrayOutputStream rspBodyBytes = new ByteArrayOutputStream(); + for (int len = content.read(tmp); len >= 0; len = content.read(tmp)) { + rspBodyBytes.write(tmp, 0, len); + } + String decodedContent = rspBodyBytes.toString("UTF-8"); + assertEquals(text, decodedContent); + } + + @Test public void jsonGzipResponse() throws Exception { + String text = "{\"Message\": { \"text\": \"Hello, World!\" } }"; + ByteArrayOutputStream bodyBytes = new ByteArrayOutputStream(); + OutputStreamWriter body = new OutputStreamWriter(new GZIPOutputStream(bodyBytes), + Charset.forName("UTF-8")); + body.write(text); + body.close(); + server.enqueue(new MockResponse().setBody(bodyBytes.toByteArray()) + .setHeader("Content-Encoding", "gzip") + .setHeader("Content-Type", "application/json")); + + byte[] tmp = new byte[32]; + + HttpGet request1 = new HttpGet(server.getUrl("/").toURI()); + request1.setHeader("Accept-encoding", "gzip"); // not transparent gzip + HttpResponse response1 = client.execute(request1); + Header[] headers1a = response1.getHeaders("Content-Encoding"); + assertEquals(1, headers1a.length); + assertEquals("gzip", headers1a[0].getValue()); + assertNotNull(response1.getEntity().getContentEncoding()); + assertEquals("gzip", response1.getEntity().getContentEncoding().getValue()); + Header[] headers1b = response1.getHeaders("Content-Type"); + assertEquals(1, headers1b.length); + assertEquals("application/json", headers1b[0].getValue()); + assertNotNull(response1.getEntity().getContentType()); + assertEquals("application/json", response1.getEntity().getContentType().getValue()); + InputStream content = new GZIPInputStream(response1.getEntity().getContent()); + ByteArrayOutputStream rspBodyBytes = new ByteArrayOutputStream(); + for (int len = content.read(tmp); len >= 0; len = content.read(tmp)) { + rspBodyBytes.write(tmp, 0, len); + } + String decodedContent = rspBodyBytes.toString("UTF-8"); + assertEquals(text, decodedContent); + } + + @Test public void jsonTransparentGzipResponse() throws Exception { + String text = "{\"Message\": { \"text\": \"Hello, World!\" } }"; + ByteArrayOutputStream bodyBytes = new ByteArrayOutputStream(); + OutputStreamWriter body = new OutputStreamWriter(new GZIPOutputStream(bodyBytes), + Charset.forName("UTF-8")); + body.write(text); + body.close(); + server.enqueue(new MockResponse().setBody(bodyBytes.toByteArray()) + .setHeader("Content-Encoding", "gzip") + .setHeader("Content-Type", "application/json")); + + byte[] tmp = new byte[32]; + + HttpGet request1 = new HttpGet(server.getUrl("/").toURI()); + // expecting transparent gzip response by not adding header "Accept-encoding: gzip" + HttpResponse response1 = client.execute(request1); + Header[] headers1a = response1.getHeaders("Content-Encoding"); + assertEquals(0, headers1a.length); + assertNull(response1.getEntity().getContentEncoding()); + // content length should also be absent + Header[] headers1b = response1.getHeaders("Content-Length"); + assertEquals(0, headers1b.length); + // The following currently fails because ContentLength(-1) is returned from the entity + // assertNull(response1.getEntity().getContentLength()); + Header[] headers1c = response1.getHeaders("Content-Type"); + assertEquals(1, headers1c.length); + assertEquals("application/json", headers1c[0].getValue()); + assertNotNull(response1.getEntity().getContentType()); + assertEquals("application/json", response1.getEntity().getContentType().getValue()); + InputStream content = response1.getEntity().getContent(); + ByteArrayOutputStream rspBodyBytes = new ByteArrayOutputStream(); + for (int len = content.read(tmp); len >= 0; len = content.read(tmp)) { + rspBodyBytes.write(tmp, 0, len); + } + String decodedContent = rspBodyBytes.toString("UTF-8"); + assertEquals(text, decodedContent); + } }