1package com.squareup.okhttp.apache;
2
3import com.squareup.okhttp.mockwebserver.MockResponse;
4import com.squareup.okhttp.mockwebserver.MockWebServer;
5import com.squareup.okhttp.mockwebserver.RecordedRequest;
6import java.io.ByteArrayInputStream;
7import java.io.IOException;
8import java.io.InputStream;
9import java.net.URISyntaxException;
10import java.util.zip.GZIPInputStream;
11import okio.Buffer;
12import okio.GzipSink;
13import okio.Okio;
14import org.apache.http.Header;
15import org.apache.http.HttpEntity;
16import org.apache.http.HttpResponse;
17import org.apache.http.client.methods.HttpGet;
18import org.apache.http.client.methods.HttpPost;
19import org.apache.http.entity.ByteArrayEntity;
20import org.apache.http.entity.InputStreamEntity;
21import org.apache.http.entity.StringEntity;
22import org.apache.http.util.EntityUtils;
23import org.junit.After;
24import org.junit.Before;
25import org.junit.Test;
26
27import static com.squareup.okhttp.internal.Util.UTF_8;
28import static org.junit.Assert.assertEquals;
29import static org.junit.Assert.assertNotNull;
30import static org.junit.Assert.assertNull;
31
32public class OkApacheClientTest {
33  private MockWebServer server;
34  private OkApacheClient client;
35
36  @Before public void setUp() throws IOException {
37    client = new OkApacheClient();
38    server = new MockWebServer();
39    server.start();
40  }
41
42  @After public void tearDown() throws IOException {
43    server.shutdown();
44  }
45
46  @Test public void success() throws Exception {
47    server.enqueue(new MockResponse().setBody("Hello, World!"));
48
49    HttpGet request = new HttpGet(server.getUrl("/").toURI());
50    HttpResponse response = client.execute(request);
51    String actual = EntityUtils.toString(response.getEntity());
52    assertEquals("Hello, World!", actual);
53  }
54
55  @Test public void redirect() throws Exception {
56    server.enqueue(new MockResponse().setResponseCode(302).addHeader("Location", "/foo"));
57    server.enqueue(new MockResponse().setBody("Hello, Redirect!"));
58
59    HttpGet request = new HttpGet(server.getUrl("/").toURI());
60    HttpResponse response = client.execute(request);
61    String actual = EntityUtils.toString(response.getEntity(), UTF_8);
62    assertEquals("Hello, Redirect!", actual);
63  }
64
65  @Test public void sessionExpired() throws Exception {
66    server.enqueue(new MockResponse().setResponseCode(422));
67
68    HttpGet request = new HttpGet(server.getUrl("/").toURI());
69    HttpResponse response = client.execute(request);
70    assertEquals(422, response.getStatusLine().getStatusCode());
71  }
72
73  @Test public void headers() throws Exception {
74    server.enqueue(new MockResponse().addHeader("Foo", "Bar"));
75    server.enqueue(new MockResponse().addHeader("Foo", "Bar").addHeader("Foo", "Baz"));
76
77    HttpGet request1 = new HttpGet(server.getUrl("/").toURI());
78    HttpResponse response1 = client.execute(request1);
79    Header[] headers1 = response1.getHeaders("Foo");
80    assertEquals(1, headers1.length);
81    assertEquals("Bar", headers1[0].getValue());
82
83    HttpGet request2 = new HttpGet(server.getUrl("/").toURI());
84    HttpResponse response2 = client.execute(request2);
85    Header[] headers2 = response2.getHeaders("Foo");
86    assertEquals(2, headers2.length);
87    assertEquals("Bar", headers2[0].getValue());
88    assertEquals("Baz", headers2[1].getValue());
89  }
90
91  @Test public void postByteEntity() throws Exception {
92    server.enqueue(new MockResponse());
93
94    final HttpPost post = new HttpPost(server.getUrl("/").toURI());
95    byte[] body = "Hello, world!".getBytes(UTF_8);
96    post.setEntity(new ByteArrayEntity(body));
97    client.execute(post);
98
99    RecordedRequest request = server.takeRequest();
100    assertEquals("Hello, world!", request.getBody().readUtf8());
101    assertEquals(request.getHeader("Content-Length"), "13");
102  }
103
104  @Test public void postInputStreamEntity() throws Exception {
105    server.enqueue(new MockResponse());
106
107    final HttpPost post = new HttpPost(server.getUrl("/").toURI());
108    byte[] body = "Hello, world!".getBytes(UTF_8);
109    post.setEntity(new InputStreamEntity(new ByteArrayInputStream(body), body.length));
110    client.execute(post);
111
112    RecordedRequest request = server.takeRequest();
113    assertEquals("Hello, world!", request.getBody().readUtf8());
114    assertEquals(request.getHeader("Content-Length"), "13");
115  }
116
117  @Test public void postOverrideContentType() throws Exception {
118    server.enqueue(new MockResponse());
119
120    HttpPost httpPost = new HttpPost();
121    httpPost.setURI(server.getUrl("/").toURI());
122    httpPost.addHeader("Content-Type", "application/xml");
123    httpPost.setEntity(new StringEntity("<yo/>"));
124    client.execute(httpPost);
125
126    RecordedRequest request = server.takeRequest();
127    assertEquals(request.getHeader("Content-Type"), "application/xml");
128  }
129
130  @Test public void contentType() throws Exception {
131    server.enqueue(new MockResponse().setBody("<html><body><h1>Hello, World!</h1></body></html>")
132        .setHeader("Content-Type", "text/html"));
133    server.enqueue(new MockResponse().setBody("{\"Message\": { \"text\": \"Hello, World!\" } }")
134        .setHeader("Content-Type", "application/json"));
135    server.enqueue(new MockResponse().setBody("Hello, World!"));
136
137    HttpGet request1 = new HttpGet(server.getUrl("/").toURI());
138    HttpResponse response1 = client.execute(request1);
139    Header[] headers1 = response1.getHeaders("Content-Type");
140    assertEquals(1, headers1.length);
141    assertEquals("text/html", headers1[0].getValue());
142    assertNotNull(response1.getEntity().getContentType());
143    assertEquals("text/html", response1.getEntity().getContentType().getValue());
144
145    HttpGet request2 = new HttpGet(server.getUrl("/").toURI());
146    HttpResponse response2 = client.execute(request2);
147    Header[] headers2 = response2.getHeaders("Content-Type");
148    assertEquals(1, headers2.length);
149    assertEquals("application/json", headers2[0].getValue());
150    assertNotNull(response2.getEntity().getContentType());
151    assertEquals("application/json", response2.getEntity().getContentType().getValue());
152
153    HttpGet request3 = new HttpGet(server.getUrl("/").toURI());
154    HttpResponse response3 = client.execute(request3);
155    Header[] headers3 = response3.getHeaders("Content-Type");
156    assertEquals(0, headers3.length);
157    assertNull(response3.getEntity().getContentType());
158  }
159
160  @Test public void contentTypeIsCaseInsensitive() throws URISyntaxException, IOException {
161    server.enqueue(new MockResponse().setBody("{\"Message\": { \"text\": \"Hello, World!\" } }")
162        .setHeader("cONTENT-tYPE", "application/json"));
163
164    HttpGet request = new HttpGet(server.getUrl("/").toURI());
165    HttpResponse response = client.execute(request);
166    assertEquals("application/json", response.getEntity().getContentType().getValue());
167  }
168
169  @Test public void contentEncoding() throws Exception {
170    String text = "{\"Message\": { \"text\": \"Hello, World!\" } }";
171    server.enqueue(new MockResponse().setBody(gzip(text))
172        .setHeader("Content-Encoding", "gzip"));
173
174    HttpGet request = new HttpGet(server.getUrl("/").toURI());
175    request.setHeader("Accept-encoding", "gzip"); // Not transparent gzip.
176    HttpResponse response = client.execute(request);
177    HttpEntity entity = response.getEntity();
178
179    Header[] encodingHeaders = response.getHeaders("Content-Encoding");
180    assertEquals(1, encodingHeaders.length);
181    assertEquals("gzip", encodingHeaders[0].getValue());
182    assertNotNull(entity.getContentEncoding());
183    assertEquals("gzip", entity.getContentEncoding().getValue());
184
185    assertEquals(text, gunzip(entity));
186  }
187
188  @Test public void jsonGzipResponse() throws Exception {
189    String text = "{\"Message\": { \"text\": \"Hello, World!\" } }";
190    server.enqueue(new MockResponse().setBody(gzip(text))
191        .setHeader("Content-Encoding", "gzip")
192        .setHeader("Content-Type", "application/json"));
193
194    HttpGet request1 = new HttpGet(server.getUrl("/").toURI());
195    request1.setHeader("Accept-encoding", "gzip"); // Not transparent gzip.
196
197    HttpResponse response = client.execute(request1);
198    HttpEntity entity = response.getEntity();
199
200    Header[] encodingHeaders = response.getHeaders("Content-Encoding");
201    assertEquals(1, encodingHeaders.length);
202    assertEquals("gzip", encodingHeaders[0].getValue());
203    assertNotNull(entity.getContentEncoding());
204    assertEquals("gzip", entity.getContentEncoding().getValue());
205
206    Header[] typeHeaders = response.getHeaders("Content-Type");
207    assertEquals(1, typeHeaders.length);
208    assertEquals("application/json", typeHeaders[0].getValue());
209    assertNotNull(entity.getContentType());
210    assertEquals("application/json", entity.getContentType().getValue());
211
212    assertEquals(text, gunzip(entity));
213  }
214
215  @Test public void jsonTransparentGzipResponse() throws Exception {
216    String text = "{\"Message\": { \"text\": \"Hello, World!\" } }";
217    server.enqueue(new MockResponse().setBody(gzip(text))
218        .setHeader("Content-Encoding", "gzip")
219        .setHeader("Content-Type", "application/json"));
220
221    HttpGet request = new HttpGet(server.getUrl("/").toURI());
222    HttpResponse response = client.execute(request);
223    HttpEntity entity = response.getEntity();
224
225    // Expecting transparent gzip response by not adding header "Accept-encoding: gzip"
226    Header[] encodingHeaders = response.getHeaders("Content-Encoding");
227    assertEquals(0, encodingHeaders.length);
228    assertNull(entity.getContentEncoding());
229
230    // Content length should be absent.
231    Header[] lengthHeaders = response.getHeaders("Content-Length");
232    assertEquals(0, lengthHeaders.length);
233    assertEquals(-1, entity.getContentLength());
234
235    Header[] typeHeaders = response.getHeaders("Content-Type");
236    assertEquals(1, typeHeaders.length);
237    assertEquals("application/json", typeHeaders[0].getValue());
238    assertNotNull(entity.getContentType());
239    assertEquals("application/json", entity.getContentType().getValue());
240
241    assertEquals(text, EntityUtils.toString(entity, UTF_8));
242  }
243
244  private static Buffer gzip(String body) throws IOException {
245    Buffer buffer = new Buffer();
246    Okio.buffer(new GzipSink(buffer)).writeUtf8(body).close();
247    return buffer;
248  }
249
250  private static String gunzip(HttpEntity body) throws IOException {
251    InputStream in = new GZIPInputStream(body.getContent());
252    Buffer buffer = new Buffer();
253    byte[] temp = new byte[1024];
254    int read;
255    while ((read = in.read(temp)) != -1) {
256      buffer.write(temp, 0, read);
257    }
258    return buffer.readUtf8();
259  }
260}
261