13c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller/*
23c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * Copyright (C) 2014 Square, Inc.
33c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller *
43c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * Licensed under the Apache License, Version 2.0 (the "License");
53c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * you may not use this file except in compliance with the License.
63c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * You may obtain a copy of the License at
73c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller *
83c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller *      http://www.apache.org/licenses/LICENSE-2.0
93c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller *
103c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * Unless required by applicable law or agreed to in writing, software
113c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * distributed under the License is distributed on an "AS IS" BASIS,
123c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * See the License for the specific language governing permissions and
143c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * limitations under the License.
153c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller */
163c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerpackage com.squareup.okhttp;
173c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
183c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport com.squareup.okhttp.internal.RecordingHostnameVerifier;
193c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport com.squareup.okhttp.internal.SslContextBuilder;
203c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport com.squareup.okhttp.mockwebserver.MockResponse;
213c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport com.squareup.okhttp.mockwebserver.MockWebServer;
223c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport com.squareup.okhttp.mockwebserver.RecordedRequest;
233c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport com.squareup.okhttp.mockwebserver.SocketPolicy;
243c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport java.io.File;
253c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport java.io.IOException;
263c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport java.net.HttpURLConnection;
273c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport java.util.UUID;
283c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport javax.net.ssl.SSLContext;
293c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport org.junit.After;
303c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport org.junit.Before;
313c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport org.junit.Test;
323c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
333c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport static org.junit.Assert.assertEquals;
343c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport static org.junit.Assert.assertNull;
353c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport static org.junit.Assert.assertTrue;
363c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport static org.junit.Assert.fail;
373c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
383c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerpublic final class SyncApiTest {
393c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  private MockWebServer server = new MockWebServer();
403c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  private OkHttpClient client = new OkHttpClient();
413c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
423c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  private static final SSLContext sslContext = SslContextBuilder.localhost();
433c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  private HttpResponseCache cache;
443c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
453c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  @Before public void setUp() throws Exception {
463c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    String tmp = System.getProperty("java.io.tmpdir");
473c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    File cacheDir = new File(tmp, "HttpCache-" + UUID.randomUUID());
483c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    cache = new HttpResponseCache(cacheDir, Integer.MAX_VALUE);
493c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
503c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
513c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  @After public void tearDown() throws Exception {
523c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    server.shutdown();
533c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    cache.delete();
543c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
553c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
563c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  @Test public void get() throws Exception {
573c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    server.enqueue(new MockResponse()
583c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .setBody("abc")
593c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .addHeader("Content-Type: text/plain"));
603c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    server.play();
613c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
623c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    Request request = new Request.Builder()
633c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .url(server.getUrl("/"))
643c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .header("User-Agent", "SyncApiTest")
653c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .build();
663c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
673c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    onSuccess(request)
683c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .assertCode(200)
693c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .assertContainsHeaders("Content-Type: text/plain")
703c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .assertBody("abc");
713c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
723c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    assertTrue(server.takeRequest().getHeaders().contains("User-Agent: SyncApiTest"));
733c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
743c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
753c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  @Test public void connectionPooling() throws Exception {
763c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    server.enqueue(new MockResponse().setBody("abc"));
773c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    server.enqueue(new MockResponse().setBody("def"));
783c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    server.enqueue(new MockResponse().setBody("ghi"));
793c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    server.play();
803c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
813c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    onSuccess(new Request.Builder().url(server.getUrl("/a")).build())
823c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .assertBody("abc");
833c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
843c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    onSuccess(new Request.Builder().url(server.getUrl("/b")).build())
853c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .assertBody("def");
863c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
873c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    onSuccess(new Request.Builder().url(server.getUrl("/c")).build())
883c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .assertBody("ghi");
893c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
903c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    assertEquals(0, server.takeRequest().getSequenceNumber());
913c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    assertEquals(1, server.takeRequest().getSequenceNumber());
923c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    assertEquals(2, server.takeRequest().getSequenceNumber());
933c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
943c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
953c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  @Test public void tls() throws Exception {
963c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    server.useHttps(sslContext.getSocketFactory(), false);
973c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    server.enqueue(new MockResponse()
983c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .setBody("abc")
993c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .addHeader("Content-Type: text/plain"));
1003c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    server.play();
1013c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
1023c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    client.setSslSocketFactory(sslContext.getSocketFactory());
1033c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    client.setHostnameVerifier(new RecordingHostnameVerifier());
1043c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
1053c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    onSuccess(new Request.Builder().url(server.getUrl("/")).build())
1063c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .assertHandshake();
1073c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
1083c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
1093c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  @Test public void recoverFromTlsHandshakeFailure() throws Exception {
1103c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    server.useHttps(sslContext.getSocketFactory(), false);
1113c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    server.enqueue(new MockResponse().setSocketPolicy(SocketPolicy.FAIL_HANDSHAKE));
1123c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    server.enqueue(new MockResponse().setBody("abc"));
1133c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    server.play();
1143c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
1153c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    client.setSslSocketFactory(sslContext.getSocketFactory());
1163c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    client.setHostnameVerifier(new RecordingHostnameVerifier());
1173c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
1183c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    onSuccess(new Request.Builder().url(server.getUrl("/")).build())
1193c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .assertBody("abc");
1203c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
1213c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
1223c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  @Test public void post() throws Exception {
1233c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    server.enqueue(new MockResponse().setBody("abc"));
1243c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    server.play();
1253c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
1263c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    Request request = new Request.Builder()
1273c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .url(server.getUrl("/"))
1283c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .post(Request.Body.create(MediaType.parse("text/plain"), "def"))
1293c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .build();
1303c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
1313c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    onSuccess(request)
1323c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .assertCode(200)
1333c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .assertBody("abc");
1343c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
1353c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    RecordedRequest recordedRequest = server.takeRequest();
1363c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    assertEquals("def", recordedRequest.getUtf8Body());
1373c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    assertEquals("3", recordedRequest.getHeader("Content-Length"));
1383c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    assertEquals("text/plain; charset=utf-8", recordedRequest.getHeader("Content-Type"));
1393c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
1403c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
141c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller  @Test public void conditionalCacheHit() throws Exception {
1423c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    server.enqueue(new MockResponse().setBody("A").addHeader("ETag: v1"));
143c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller    server.enqueue(new MockResponse()
144c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller        .clearHeaders()
145c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller        .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));
1463c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    server.play();
1473c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
1483c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    client.setOkResponseCache(cache);
1493c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
1503c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    onSuccess(new Request.Builder().url(server.getUrl("/")).build())
1513c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .assertCode(200).assertBody("A");
1523c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    assertNull(server.takeRequest().getHeader("If-None-Match"));
1533c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
1543c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    onSuccess(new Request.Builder().url(server.getUrl("/")).build())
1553c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .assertCode(200).assertBody("A");
1563c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    assertEquals("v1", server.takeRequest().getHeader("If-None-Match"));
1573c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
1583c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
159c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller  @Test public void conditionalCacheMiss() throws Exception {
160c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller    server.enqueue(new MockResponse().setBody("A").addHeader("ETag: v1"));
161c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller    server.enqueue(new MockResponse().setBody("B"));
162c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller    server.play();
163c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller
164c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller    client.setOkResponseCache(cache);
165c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller
166c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller    onSuccess(new Request.Builder().url(server.getUrl("/")).build())
167c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller        .assertCode(200).assertBody("A");
168c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller    assertNull(server.takeRequest().getHeader("If-None-Match"));
169c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller
170c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller    onSuccess(new Request.Builder().url(server.getUrl("/")).build())
171c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller        .assertCode(200).assertBody("B");
172c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller    assertEquals("v1", server.takeRequest().getHeader("If-None-Match"));
173c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller  }
174c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller
1753c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  @Test public void redirect() throws Exception {
1763c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    server.enqueue(new MockResponse()
1773c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .setResponseCode(301)
1783c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .addHeader("Location: /b")
1793c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .addHeader("Test", "Redirect from /a to /b")
1803c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .setBody("/a has moved!"));
1813c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    server.enqueue(new MockResponse()
1823c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .setResponseCode(302)
1833c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .addHeader("Location: /c")
1843c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .addHeader("Test", "Redirect from /b to /c")
1853c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .setBody("/b has moved!"));
1863c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    server.enqueue(new MockResponse().setBody("C"));
1873c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    server.play();
1883c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
1893c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    onSuccess(new Request.Builder().url(server.getUrl("/a")).build())
1903c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .assertCode(200)
1913c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .assertBody("C")
1923c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .redirectedBy()
1933c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .assertCode(302)
1943c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .assertContainsHeaders("Test: Redirect from /b to /c")
1953c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .redirectedBy()
1963c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .assertCode(301)
1973c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .assertContainsHeaders("Test: Redirect from /a to /b");
1983c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
1993c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    assertEquals(0, server.takeRequest().getSequenceNumber()); // New connection.
2003c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    assertEquals(1, server.takeRequest().getSequenceNumber()); // Connection reused.
2013c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    assertEquals(2, server.takeRequest().getSequenceNumber()); // Connection reused again!
2023c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
2033c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
2043c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  @Test public void redirectWithRedirectsDisabled() throws Exception {
2053c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    client.setFollowProtocolRedirects(false);
2063c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    server.enqueue(new MockResponse()
2073c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .setResponseCode(301)
2083c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .addHeader("Location: /b")
2093c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .addHeader("Test", "Redirect from /a to /b")
2103c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .setBody("/a has moved!"));
2113c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    server.play();
2123c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
2133c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    onSuccess(new Request.Builder().url(server.getUrl("/a")).build())
2143c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .assertCode(301)
2153c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .assertBody("/a has moved!")
2163c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .assertContainsHeaders("Location: /b");
2173c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
2183c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
2193c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  @Test public void follow20Redirects() throws Exception {
2203c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    for (int i = 0; i < 20; i++) {
2213c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      server.enqueue(new MockResponse()
2223c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller          .setResponseCode(301)
2233c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller          .addHeader("Location: /" + (i + 1))
2243c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller          .setBody("Redirecting to /" + (i + 1)));
2253c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    }
2263c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    server.enqueue(new MockResponse().setBody("Success!"));
2273c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    server.play();
2283c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
2293c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    onSuccess(new Request.Builder().url(server.getUrl("/0")).build())
2303c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .assertCode(200)
2313c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .assertBody("Success!");
2323c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
2333c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
2343c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  @Test public void doesNotFollow21Redirects() throws Exception {
2353c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    for (int i = 0; i < 21; i++) {
2363c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      server.enqueue(new MockResponse()
2373c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller          .setResponseCode(301)
2383c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller          .addHeader("Location: /" + (i + 1))
2393c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller          .setBody("Redirecting to /" + (i + 1)));
2403c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    }
2413c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    server.play();
2423c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
2433c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    try {
2443c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      client.execute(new Request.Builder().url(server.getUrl("/0")).build());
2453c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      fail();
2463c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    } catch (IOException e) {
2473c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      assertEquals("Too many redirects: 21", e.getMessage());
2483c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    }
2493c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
2503c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
2513c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  @Test public void postBodyRetransmittedOnRedirect() throws Exception {
2523c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    server.enqueue(new MockResponse()
2533c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .setResponseCode(302)
2543c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .addHeader("Location: /b")
2553c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .setBody("Moved to /b !"));
2563c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    server.enqueue(new MockResponse()
2573c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .setBody("This is b."));
2583c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    server.play();
2593c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
2603c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    Request request = new Request.Builder()
2613c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .url(server.getUrl("/"))
2623c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .post(Request.Body.create(MediaType.parse("text/plain"), "body!"))
2633c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .build();
2643c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
2653c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    onSuccess(request)
2663c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .assertCode(200)
2673c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        .assertBody("This is b.");
2683c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
2693c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    RecordedRequest request1 = server.takeRequest();
2703c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    assertEquals("body!", request1.getUtf8Body());
2713c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    assertEquals("5", request1.getHeader("Content-Length"));
2723c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    assertEquals("text/plain; charset=utf-8", request1.getHeader("Content-Type"));
2733c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    assertEquals(0, request1.getSequenceNumber());
2743c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
2753c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    RecordedRequest request2 = server.takeRequest();
2763c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    assertEquals("body!", request2.getUtf8Body());
2773c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    assertEquals("5", request2.getHeader("Content-Length"));
2783c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    assertEquals("text/plain; charset=utf-8", request2.getHeader("Content-Type"));
2793c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    assertEquals(1, request2.getSequenceNumber());
2803c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
2813c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
2823c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  private RecordedResponse onSuccess(Request request) throws IOException {
2833c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    Response response = client.execute(request);
2843c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    return new RecordedResponse(request, response, response.body().string(), null);
2853c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
2863c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller}
287