13c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller/* 23c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * Copyright (C) 2013 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.internal.http; 173c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 183c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport com.squareup.okhttp.HttpResponseCache; 193c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport com.squareup.okhttp.OkHttpClient; 203c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport com.squareup.okhttp.Protocol; 213c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport com.squareup.okhttp.internal.RecordingAuthenticator; 223c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport com.squareup.okhttp.internal.SslContextBuilder; 233c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport com.squareup.okhttp.internal.Util; 243c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport com.squareup.okhttp.mockwebserver.MockResponse; 253c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport com.squareup.okhttp.mockwebserver.MockWebServer; 263c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport com.squareup.okhttp.mockwebserver.RecordedRequest; 273c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport com.squareup.okhttp.mockwebserver.SocketPolicy; 283c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport java.io.ByteArrayOutputStream; 293c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport java.io.File; 303c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport java.io.IOException; 313c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport java.io.InputStream; 323c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport java.io.OutputStream; 333c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport java.net.Authenticator; 343c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport java.net.CookieManager; 353c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport java.net.HttpURLConnection; 363c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport java.net.URL; 373c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport java.util.Arrays; 383c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport java.util.Collection; 393c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport java.util.Collections; 403c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport java.util.List; 413c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport java.util.Map; 423c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport java.util.UUID; 433c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport java.util.concurrent.CountDownLatch; 443c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport java.util.concurrent.ExecutorService; 453c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport java.util.concurrent.Executors; 463c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport java.util.zip.GZIPOutputStream; 473c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport javax.net.ssl.HostnameVerifier; 483c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport javax.net.ssl.SSLContext; 493c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport javax.net.ssl.SSLSession; 503c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport org.junit.After; 513c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport org.junit.Before; 523c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport org.junit.Ignore; 533c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport org.junit.Test; 543c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 553c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport static java.util.concurrent.TimeUnit.SECONDS; 563c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport static org.junit.Assert.assertArrayEquals; 573c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport static org.junit.Assert.assertEquals; 583c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport static org.junit.Assert.assertNull; 593c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport static org.junit.Assert.assertTrue; 603c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport static org.junit.Assert.fail; 613c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 623c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller/** Test how SPDY interacts with HTTP features. */ 633c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerpublic abstract class HttpOverSpdyTest { 643c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 653c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller /** Protocol to test, for example {@link com.squareup.okhttp.Protocol#SPDY_3} */ 663c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller private final Protocol protocol; 673c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller protected String hostHeader = ":host"; 683c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 693c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller protected HttpOverSpdyTest(Protocol protocol){ 703c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller this.protocol = protocol; 713c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 723c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 733c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller private static final HostnameVerifier NULL_HOSTNAME_VERIFIER = new HostnameVerifier() { 743c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller public boolean verify(String hostname, SSLSession session) { 753c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller return true; 763c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 773c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller }; 783c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 793c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller private static final SSLContext sslContext = SslContextBuilder.localhost(); 803c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller protected final MockWebServer server = new MockWebServer(); 813c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller protected final String hostName = server.getHostName(); 823c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller protected final OkHttpClient client = new OkHttpClient(); 833c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller protected HttpURLConnection connection; 843c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller protected HttpResponseCache cache; 853c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 863c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Before public void setUp() throws Exception { 873c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller server.useHttps(sslContext.getSocketFactory(), false); 883c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller client.setProtocols(Arrays.asList(protocol, Protocol.HTTP_11)); 893c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller client.setSslSocketFactory(sslContext.getSocketFactory()); 903c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller client.setHostnameVerifier(NULL_HOSTNAME_VERIFIER); 913c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller String systemTmpDir = System.getProperty("java.io.tmpdir"); 923c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller File cacheDir = new File(systemTmpDir, "HttpCache-" + protocol + "-" + UUID.randomUUID()); 933c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller cache = new HttpResponseCache(cacheDir, Integer.MAX_VALUE); 943c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 953c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 963c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @After public void tearDown() throws Exception { 973c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller Authenticator.setDefault(null); 983c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller server.shutdown(); 993c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 1003c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 1013c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Test public void get() throws Exception { 1023c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller MockResponse response = new MockResponse().setBody("ABCDE").setStatus("HTTP/1.1 200 Sweet"); 1033c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller server.enqueue(response); 1043c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller server.play(); 1053c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 1063c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/foo")); 1073c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertContent("ABCDE", connection, Integer.MAX_VALUE); 1083c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals(200, connection.getResponseCode()); 1093c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals("Sweet", connection.getResponseMessage()); 1103c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 1113c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller RecordedRequest request = server.takeRequest(); 1123c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals("GET /foo HTTP/1.1", request.getRequestLine()); 1133c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertContains(request.getHeaders(), ":scheme: https"); 1143c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertContains(request.getHeaders(), hostHeader + ": " + hostName + ":" + server.getPort()); 1153c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 1163c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 1173c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Test public void emptyResponse() throws IOException { 1183c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller server.enqueue(new MockResponse()); 1193c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller server.play(); 1203c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 1213c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/foo")); 1223c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals(-1, connection.getInputStream().read()); 1233c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 1243c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 1253c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller byte[] postBytes = "FGHIJ".getBytes(Util.UTF_8); 1263c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 1273c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller /** An output stream can be written to more than once, so we can't guess content length. */ 1283c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Test public void noDefaultContentLengthOnPost() throws Exception { 1293c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller MockResponse response = new MockResponse().setBody("ABCDE"); 1303c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller server.enqueue(response); 1313c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller server.play(); 1323c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 1333c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/foo")); 1343c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection.setDoOutput(true); 1353c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection.getOutputStream().write(postBytes); 1363c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertContent("ABCDE", connection, Integer.MAX_VALUE); 1373c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 1383c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller RecordedRequest request = server.takeRequest(); 1393c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals("POST /foo HTTP/1.1", request.getRequestLine()); 1403c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertArrayEquals(postBytes, request.getBody()); 1413c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertNull(request.getHeader("Content-Length")); 1423c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 1433c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 1443c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Test public void userSuppliedContentLengthHeader() throws Exception { 1453c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller MockResponse response = new MockResponse().setBody("ABCDE"); 1463c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller server.enqueue(response); 1473c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller server.play(); 1483c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 1493c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/foo")); 1503c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection.setRequestProperty("Content-Length", String.valueOf(postBytes.length)); 1513c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection.setDoOutput(true); 1523c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection.getOutputStream().write(postBytes); 1533c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertContent("ABCDE", connection, Integer.MAX_VALUE); 1543c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 1553c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller RecordedRequest request = server.takeRequest(); 1563c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals("POST /foo HTTP/1.1", request.getRequestLine()); 1573c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertArrayEquals(postBytes, request.getBody()); 1583c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals(postBytes.length, Integer.parseInt(request.getHeader("Content-Length"))); 1593c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 1603c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 1613c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Test public void closeAfterFlush() throws Exception { 1623c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller MockResponse response = new MockResponse().setBody("ABCDE"); 1633c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller server.enqueue(response); 1643c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller server.play(); 1653c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 1663c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/foo")); 1673c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection.setRequestProperty("Content-Length", String.valueOf(postBytes.length)); 1683c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection.setDoOutput(true); 1693c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection.getOutputStream().write(postBytes); // push bytes into SpdyDataOutputStream.buffer 1703c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection.getOutputStream().flush(); // SpdyConnection.writeData subject to write window 1713c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection.getOutputStream().close(); // SpdyConnection.writeData empty frame 1723c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertContent("ABCDE", connection, Integer.MAX_VALUE); 1733c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 1743c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller RecordedRequest request = server.takeRequest(); 1753c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals("POST /foo HTTP/1.1", request.getRequestLine()); 1763c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertArrayEquals(postBytes, request.getBody()); 1773c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals(postBytes.length, Integer.parseInt(request.getHeader("Content-Length"))); 1783c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 1793c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 1803c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Test public void setFixedLengthStreamingModeSetsContentLength() throws Exception { 1813c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller MockResponse response = new MockResponse().setBody("ABCDE"); 1823c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller server.enqueue(response); 1833c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller server.play(); 1843c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 1853c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/foo")); 1863c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection.setFixedLengthStreamingMode(postBytes.length); 1873c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection.setDoOutput(true); 1883c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection.getOutputStream().write(postBytes); 1893c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertContent("ABCDE", connection, Integer.MAX_VALUE); 1903c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 1913c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller RecordedRequest request = server.takeRequest(); 1923c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals("POST /foo HTTP/1.1", request.getRequestLine()); 1933c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertArrayEquals(postBytes, request.getBody()); 1943c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals(postBytes.length, Integer.parseInt(request.getHeader("Content-Length"))); 1953c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 1963c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 1973c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Test public void spdyConnectionReuse() throws Exception { 1983c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller server.enqueue(new MockResponse().setBody("ABCDEF")); 1993c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller server.enqueue(new MockResponse().setBody("GHIJKL")); 2003c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller server.play(); 2013c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 2023c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller HttpURLConnection connection1 = client.open(server.getUrl("/r1")); 2033c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller HttpURLConnection connection2 = client.open(server.getUrl("/r2")); 2043c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals("ABC", readAscii(connection1.getInputStream(), 3)); 2053c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals("GHI", readAscii(connection2.getInputStream(), 3)); 2063c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals("DEF", readAscii(connection1.getInputStream(), 3)); 2073c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals("JKL", readAscii(connection2.getInputStream(), 3)); 2083c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals(0, server.takeRequest().getSequenceNumber()); 2093c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals(1, server.takeRequest().getSequenceNumber()); 2103c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 2113c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 2123c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Test @Ignore public void synchronousSpdyRequest() throws Exception { 2133c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller server.enqueue(new MockResponse().setBody("A")); 2143c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller server.enqueue(new MockResponse().setBody("A")); 2153c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller server.play(); 2163c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 2173c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller ExecutorService executor = Executors.newCachedThreadPool(); 2183c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller CountDownLatch countDownLatch = new CountDownLatch(2); 2193c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller executor.execute(new SpdyRequest("/r1", countDownLatch)); 2203c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller executor.execute(new SpdyRequest("/r2", countDownLatch)); 2213c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller countDownLatch.await(); 2223c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals(0, server.takeRequest().getSequenceNumber()); 2233c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals(1, server.takeRequest().getSequenceNumber()); 2243c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 2253c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 2263c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Test public void gzippedResponseBody() throws Exception { 2273c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller server.enqueue(new MockResponse().addHeader("Content-Encoding: gzip") 2283c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller .setBody(gzip("ABCABCABC".getBytes(Util.UTF_8)))); 2293c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller server.play(); 2303c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertContent("ABCABCABC", client.open(server.getUrl("/r1")), Integer.MAX_VALUE); 2313c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 2323c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 2333c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Test public void authenticate() throws Exception { 2343c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_UNAUTHORIZED) 2353c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller .addHeader("www-authenticate: Basic realm=\"protected area\"") 2363c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller .setBody("Please authenticate.")); 2373c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller server.enqueue(new MockResponse().setBody("Successful auth!")); 2383c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller server.play(); 2393c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 2403c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller Authenticator.setDefault(new RecordingAuthenticator()); 2413c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/")); 2423c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals("Successful auth!", readAscii(connection.getInputStream(), Integer.MAX_VALUE)); 2433c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 2443c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller RecordedRequest denied = server.takeRequest(); 2453c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertContainsNoneMatching(denied.getHeaders(), "authorization: Basic .*"); 2463c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller RecordedRequest accepted = server.takeRequest(); 2473c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals("GET / HTTP/1.1", accepted.getRequestLine()); 2483c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertContains(accepted.getHeaders(), 2493c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller "authorization: Basic " + RecordingAuthenticator.BASE_64_CREDENTIALS); 2503c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 2513c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 2523c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Test public void redirect() throws Exception { 2533c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_MOVED_TEMP) 2543c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller .addHeader("Location: /foo") 2553c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller .setBody("This page has moved!")); 2563c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller server.enqueue(new MockResponse().setBody("This is the new location!")); 2573c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller server.play(); 2583c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 2593c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/")); 2603c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertContent("This is the new location!", connection, Integer.MAX_VALUE); 2613c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 2623c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller RecordedRequest request1 = server.takeRequest(); 2633c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals("/", request1.getPath()); 2643c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller RecordedRequest request2 = server.takeRequest(); 2653c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals("/foo", request2.getPath()); 2663c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 2673c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 2683c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Test public void readAfterLastByte() throws Exception { 2693c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller server.enqueue(new MockResponse().setBody("ABC")); 2703c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller server.play(); 2713c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 2723c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/")); 2733c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller InputStream in = connection.getInputStream(); 2743c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals("ABC", readAscii(in, 3)); 2753c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals(-1, in.read()); 2763c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals(-1, in.read()); 2773c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 2783c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 2793c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Ignore // See https://github.com/square/okhttp/issues/578 2803c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Test(timeout = 3000) public void readResponseHeaderTimeout() throws Exception { 2813c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller server.enqueue(new MockResponse().setSocketPolicy(SocketPolicy.NO_RESPONSE)); 2823c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller server.enqueue(new MockResponse().setBody("A")); 2833c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller server.play(); 2843c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 2853c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/")); 2863c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection.setReadTimeout(1000); 2873c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertContent("A", connection, Integer.MAX_VALUE); 2883c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 2893c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 2903c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller /** 2913c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * Test to ensure we don't throw a read timeout on responses that are 2923c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * progressing. For this case, we take a 4KiB body and throttle it to 2933c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * 1KiB/second. We set the read timeout to two seconds. If our 2943c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * implementation is acting correctly, it will not throw, as it is 2953c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * progressing. 2963c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller */ 2973c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Test public void readTimeoutMoreGranularThanBodySize() throws Exception { 2983c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller char[] body = new char[4096]; // 4KiB to read 2993c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller Arrays.fill(body, 'y'); 3003c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller server.enqueue(new MockResponse() 3013c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller .setBody(new String(body)) 3023c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller .throttleBody(1024, 1, SECONDS)); // slow connection 1KiB/second 3033c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller server.play(); 3043c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 3053c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/")); 3063c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection.setReadTimeout(2000); // 2 seconds to read something. 3073c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertContent(new String(body), connection, Integer.MAX_VALUE); 3083c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 3093c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 3103c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller /** 3113c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * Test to ensure we throw a read timeout on responses that are progressing 3123c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * too slowly. For this case, we take a 2KiB body and throttle it to 3133c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * 1KiB/second. We set the read timeout to half a second. If our 3143c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * implementation is acting correctly, it will throw, as a byte doesn't 3153c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * arrive in time. 3163c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller */ 3173c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Test public void readTimeoutOnSlowConnection() throws Exception { 3183c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller char[] body = new char[2048]; // 2KiB to read 3193c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller Arrays.fill(body, 'y'); 3203c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller server.enqueue(new MockResponse() 3213c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller .setBody(new String(body)) 3223c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller .throttleBody(1024, 1, SECONDS)); // slow connection 1KiB/second 3233c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller server.play(); 3243c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 3253c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/")); 3263c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection.setReadTimeout(500); // half a second to read something 3273c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection.connect(); 3283c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller try { 3293c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller readAscii(connection.getInputStream(), Integer.MAX_VALUE); 3303c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller fail("Should have timed out!"); 3313c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } catch (IOException e){ 3323c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals("Read timed out", e.getMessage()); 3333c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 3343c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 3353c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 3363c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Test public void spdyConnectionTimeout() throws Exception { 3373c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller MockResponse response = new MockResponse().setBody("A"); 3383c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller response.setBodyDelayTimeMs(1000); 3393c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller server.enqueue(response); 3403c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller server.play(); 3413c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 3423c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller HttpURLConnection connection1 = client.open(server.getUrl("/")); 3433c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection1.setReadTimeout(2000); 3443c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller HttpURLConnection connection2 = client.open(server.getUrl("/")); 3453c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection2.setReadTimeout(200); 3463c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection1.connect(); 3473c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection2.connect(); 3483c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertContent("A", connection1, Integer.MAX_VALUE); 3493c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 3503c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 3513c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Test public void responsesAreCached() throws IOException { 3523c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller client.setOkResponseCache(cache); 3533c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 3543c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller server.enqueue(new MockResponse().addHeader("cache-control: max-age=60").setBody("A")); 3553c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller server.play(); 3563c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 3573c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertContent("A", client.open(server.getUrl("/")), Integer.MAX_VALUE); 3583c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals(1, cache.getRequestCount()); 3593c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals(1, cache.getNetworkCount()); 3603c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals(0, cache.getHitCount()); 3613c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertContent("A", client.open(server.getUrl("/")), Integer.MAX_VALUE); 3623c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertContent("A", client.open(server.getUrl("/")), Integer.MAX_VALUE); 3633c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals(3, cache.getRequestCount()); 3643c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals(1, cache.getNetworkCount()); 3653c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals(2, cache.getHitCount()); 3663c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 3673c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 3683c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Test public void conditionalCache() throws IOException { 3693c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller client.setOkResponseCache(cache); 3703c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 3713c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller server.enqueue(new MockResponse().addHeader("ETag: v1").setBody("A")); 3723c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED)); 3733c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller server.play(); 3743c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 3753c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertContent("A", client.open(server.getUrl("/")), Integer.MAX_VALUE); 3763c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals(1, cache.getRequestCount()); 3773c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals(1, cache.getNetworkCount()); 3783c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals(0, cache.getHitCount()); 3793c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertContent("A", client.open(server.getUrl("/")), Integer.MAX_VALUE); 3803c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals(2, cache.getRequestCount()); 3813c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals(2, cache.getNetworkCount()); 3823c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals(1, cache.getHitCount()); 3833c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 3843c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 3853c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Test public void responseCachedWithoutConsumingFullBody() throws IOException { 3863c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller client.setOkResponseCache(cache); 3873c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 3883c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller server.enqueue(new MockResponse().addHeader("cache-control: max-age=60").setBody("ABCD")); 3893c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller server.enqueue(new MockResponse().addHeader("cache-control: max-age=60").setBody("EFGH")); 3903c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller server.play(); 3913c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 3923c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller HttpURLConnection connection1 = client.open(server.getUrl("/")); 3933c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller InputStream in1 = connection1.getInputStream(); 3943c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals("AB", readAscii(in1, 2)); 3953c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller in1.close(); 3963c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 3973c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller HttpURLConnection connection2 = client.open(server.getUrl("/")); 3983c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller InputStream in2 = connection2.getInputStream(); 3993c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals("ABCD", readAscii(in2, Integer.MAX_VALUE)); 4003c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller in2.close(); 4013c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 4023c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 4033c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Test public void acceptAndTransmitCookies() throws Exception { 4043c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller CookieManager cookieManager = new CookieManager(); 4053c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller client.setCookieHandler(cookieManager); 4063c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller server.enqueue( 4073c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller new MockResponse().addHeader("set-cookie: c=oreo; domain=" + server.getCookieDomain()) 4083c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller .setBody("A")); 4093c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller server.enqueue(new MockResponse().setBody("B")); 4103c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller server.play(); 4113c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 4123c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller URL url = server.getUrl("/"); 4133c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertContent("A", client.open(url), Integer.MAX_VALUE); 4143c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller Map<String, List<String>> requestHeaders = Collections.emptyMap(); 4153c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals(Collections.singletonMap("Cookie", Arrays.asList("c=oreo")), 4163c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller cookieManager.get(url.toURI(), requestHeaders)); 4173c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 4183c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertContent("B", client.open(url), Integer.MAX_VALUE); 4193c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller RecordedRequest requestA = server.takeRequest(); 4203c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertContainsNoneMatching(requestA.getHeaders(), "Cookie.*"); 4213c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller RecordedRequest requestB = server.takeRequest(); 4223c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertContains(requestB.getHeaders(), "cookie: c=oreo"); 4233c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 4243c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 4253c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller <T> void assertContains(Collection<T> collection, T value) { 4263c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertTrue(collection.toString(), collection.contains(value)); 4273c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 4283c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 4293c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller void assertContent(String expected, HttpURLConnection connection, int limit) 4303c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller throws IOException { 4313c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection.connect(); 4323c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals(expected, readAscii(connection.getInputStream(), limit)); 4333c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 4343c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 4353c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller private void assertContainsNoneMatching(List<String> headers, String pattern) { 4363c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller for (String header : headers) { 4373c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller if (header.matches(pattern)) { 4383c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller fail("Header " + header + " matches " + pattern); 4393c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 4403c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 4413c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 4423c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 4433c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller private String readAscii(InputStream in, int count) throws IOException { 4443c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller StringBuilder result = new StringBuilder(); 4453c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller for (int i = 0; i < count; i++) { 4463c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller int value = in.read(); 4473c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller if (value == -1) { 4483c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller in.close(); 4493c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller break; 4503c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 4513c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller result.append((char) value); 4523c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 4533c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller return result.toString(); 4543c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 4553c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 4563c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller public byte[] gzip(byte[] bytes) throws IOException { 4573c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller ByteArrayOutputStream bytesOut = new ByteArrayOutputStream(); 4583c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller OutputStream gzippedOut = new GZIPOutputStream(bytesOut); 4593c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller gzippedOut.write(bytes); 4603c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller gzippedOut.close(); 4613c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller return bytesOut.toByteArray(); 4623c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 4633c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 4643c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller class SpdyRequest implements Runnable { 4653c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller String path; 4663c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller CountDownLatch countDownLatch; 4673c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller public SpdyRequest(String path, CountDownLatch countDownLatch) { 4683c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller this.path = path; 4693c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller this.countDownLatch = countDownLatch; 4703c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 4713c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 4723c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Override public void run() { 4733c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller try { 4743c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller HttpURLConnection conn = client.open(server.getUrl(path)); 4753c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals("A", readAscii(conn.getInputStream(), 1)); 4763c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller countDownLatch.countDown(); 4773c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } catch (Exception e) { 4783c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller throw new RuntimeException(e); 4793c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 4803c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 4813c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 4823c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller} 483