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