1c3f6f16bd4a2338e88275641b9f2f56e816ca377Narayan Kamath/* 2c3f6f16bd4a2338e88275641b9f2f56e816ca377Narayan Kamath * Copyright (C) 2009 The Android Open Source Project 3c3f6f16bd4a2338e88275641b9f2f56e816ca377Narayan Kamath * 4c3f6f16bd4a2338e88275641b9f2f56e816ca377Narayan Kamath * Licensed under the Apache License, Version 2.0 (the "License"); 5c3f6f16bd4a2338e88275641b9f2f56e816ca377Narayan Kamath * you may not use this file except in compliance with the License. 6c3f6f16bd4a2338e88275641b9f2f56e816ca377Narayan Kamath * You may obtain a copy of the License at 7c3f6f16bd4a2338e88275641b9f2f56e816ca377Narayan Kamath * 8c3f6f16bd4a2338e88275641b9f2f56e816ca377Narayan Kamath * http://www.apache.org/licenses/LICENSE-2.0 9c3f6f16bd4a2338e88275641b9f2f56e816ca377Narayan Kamath * 10c3f6f16bd4a2338e88275641b9f2f56e816ca377Narayan Kamath * Unless required by applicable law or agreed to in writing, software 11c3f6f16bd4a2338e88275641b9f2f56e816ca377Narayan Kamath * distributed under the License is distributed on an "AS IS" BASIS, 12c3f6f16bd4a2338e88275641b9f2f56e816ca377Narayan Kamath * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c3f6f16bd4a2338e88275641b9f2f56e816ca377Narayan Kamath * See the License for the specific language governing permissions and 14c3f6f16bd4a2338e88275641b9f2f56e816ca377Narayan Kamath * limitations under the License. 15c3f6f16bd4a2338e88275641b9f2f56e816ca377Narayan Kamath */ 16c3f6f16bd4a2338e88275641b9f2f56e816ca377Narayan Kamath 1771b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fullerpackage com.squareup.okhttp; 1871b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller 19e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport com.squareup.okhttp.internal.Internal; 206c251e20f00c7574b217bd4351ac81666f574380Tobias Thiererimport com.squareup.okhttp.internal.Platform; 2154cf3446000fdcf88a9e62724f7deb0282e98da1jwilsonimport com.squareup.okhttp.internal.RecordingAuthenticator; 22faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamathimport com.squareup.okhttp.internal.RecordingOkAuthenticator; 236c251e20f00c7574b217bd4351ac81666f574380Tobias Thiererimport com.squareup.okhttp.internal.SingleInetAddressDns; 242231db3e6bb54447a9b14cf004a6cb03c373651cjwilsonimport com.squareup.okhttp.internal.SslContextBuilder; 25e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport com.squareup.okhttp.internal.Util; 2671b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fullerimport com.squareup.okhttp.internal.Version; 27166772be0e5cfdaea1a64b9f63e4c8dbfe48cba3Narayan Kamathimport com.squareup.okhttp.mockwebserver.MockResponse; 28166772be0e5cfdaea1a64b9f63e4c8dbfe48cba3Narayan Kamathimport com.squareup.okhttp.mockwebserver.MockWebServer; 29166772be0e5cfdaea1a64b9f63e4c8dbfe48cba3Narayan Kamathimport com.squareup.okhttp.mockwebserver.RecordedRequest; 30166772be0e5cfdaea1a64b9f63e4c8dbfe48cba3Narayan Kamathimport com.squareup.okhttp.mockwebserver.SocketPolicy; 3171b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fullerimport com.squareup.okhttp.testing.RecordingHostnameVerifier; 32c3f6f16bd4a2338e88275641b9f2f56e816ca377Narayan Kamathimport java.io.IOException; 33c3f6f16bd4a2338e88275641b9f2f56e816ca377Narayan Kamathimport java.io.InputStream; 34c3f6f16bd4a2338e88275641b9f2f56e816ca377Narayan Kamathimport java.io.OutputStream; 35c3f6f16bd4a2338e88275641b9f2f56e816ca377Narayan Kamathimport java.net.Authenticator; 36c3f6f16bd4a2338e88275641b9f2f56e816ca377Narayan Kamathimport java.net.ConnectException; 37c3f6f16bd4a2338e88275641b9f2f56e816ca377Narayan Kamathimport java.net.HttpRetryException; 38c3f6f16bd4a2338e88275641b9f2f56e816ca377Narayan Kamathimport java.net.HttpURLConnection; 39c3f6f16bd4a2338e88275641b9f2f56e816ca377Narayan Kamathimport java.net.InetAddress; 40c3f6f16bd4a2338e88275641b9f2f56e816ca377Narayan Kamathimport java.net.ProtocolException; 41c3f6f16bd4a2338e88275641b9f2f56e816ca377Narayan Kamathimport java.net.Proxy; 422231db3e6bb54447a9b14cf004a6cb03c373651cjwilsonimport java.net.ProxySelector; 43e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport java.net.ServerSocket; 44a83ddf194ffbae04ce536967efff0ec72df70e10Lorenzo Colittiimport java.net.Socket; 452231db3e6bb54447a9b14cf004a6cb03c373651cjwilsonimport java.net.SocketAddress; 46b5f9076b16fcc41c3dad31aecfdcfd962a7a1f75Neil Fullerimport java.net.SocketTimeoutException; 47c3f6f16bd4a2338e88275641b9f2f56e816ca377Narayan Kamathimport java.net.URI; 48c3f6f16bd4a2338e88275641b9f2f56e816ca377Narayan Kamathimport java.net.URL; 49c3f6f16bd4a2338e88275641b9f2f56e816ca377Narayan Kamathimport java.net.URLConnection; 50c3f6f16bd4a2338e88275641b9f2f56e816ca377Narayan Kamathimport java.net.UnknownHostException; 516c251e20f00c7574b217bd4351ac81666f574380Tobias Thiererimport java.security.SecureRandom; 52c3f6f16bd4a2338e88275641b9f2f56e816ca377Narayan Kamathimport java.security.cert.CertificateException; 53c3f6f16bd4a2338e88275641b9f2f56e816ca377Narayan Kamathimport java.security.cert.X509Certificate; 54c3f6f16bd4a2338e88275641b9f2f56e816ca377Narayan Kamathimport java.util.ArrayList; 55c3f6f16bd4a2338e88275641b9f2f56e816ca377Narayan Kamathimport java.util.Arrays; 56c3f6f16bd4a2338e88275641b9f2f56e816ca377Narayan Kamathimport java.util.Collections; 57e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport java.util.EnumSet; 5871b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fullerimport java.util.LinkedHashSet; 59c3f6f16bd4a2338e88275641b9f2f56e816ca377Narayan Kamathimport java.util.List; 60c3f6f16bd4a2338e88275641b9f2f56e816ca377Narayan Kamathimport java.util.Map; 61faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamathimport java.util.Random; 62c3f6f16bd4a2338e88275641b9f2f56e816ca377Narayan Kamathimport java.util.Set; 6387ed7244fb53ae2bac9f23c033bbd5f23ac269f8Jesse Wilsonimport java.util.concurrent.TimeUnit; 64c3f6f16bd4a2338e88275641b9f2f56e816ca377Narayan Kamathimport java.util.zip.GZIPInputStream; 65e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport javax.net.ServerSocketFactory; 66a83ddf194ffbae04ce536967efff0ec72df70e10Lorenzo Colittiimport javax.net.SocketFactory; 677407d6984ce69693097befc9b72609a8156463bbNarayan Kamathimport javax.net.ssl.HttpsURLConnection; 68c3f6f16bd4a2338e88275641b9f2f56e816ca377Narayan Kamathimport javax.net.ssl.SSLContext; 69c3f6f16bd4a2338e88275641b9f2f56e816ca377Narayan Kamathimport javax.net.ssl.SSLException; 702231db3e6bb54447a9b14cf004a6cb03c373651cjwilsonimport javax.net.ssl.SSLHandshakeException; 71c3f6f16bd4a2338e88275641b9f2f56e816ca377Narayan Kamathimport javax.net.ssl.SSLSocketFactory; 722231db3e6bb54447a9b14cf004a6cb03c373651cjwilsonimport javax.net.ssl.TrustManager; 73c3f6f16bd4a2338e88275641b9f2f56e816ca377Narayan Kamathimport javax.net.ssl.X509TrustManager; 74e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport okio.Buffer; 75e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport okio.BufferedSink; 76e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport okio.GzipSink; 77e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport okio.Okio; 782231db3e6bb54447a9b14cf004a6cb03c373651cjwilsonimport org.junit.After; 7954cf3446000fdcf88a9e62724f7deb0282e98da1jwilsonimport org.junit.Before; 8054cf3446000fdcf88a9e62724f7deb0282e98da1jwilsonimport org.junit.Ignore; 81e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport org.junit.Rule; 8254cf3446000fdcf88a9e62724f7deb0282e98da1jwilsonimport org.junit.Test; 83e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport org.junit.rules.TemporaryFolder; 8454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 853c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport static com.squareup.okhttp.internal.Util.UTF_8; 863c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport static com.squareup.okhttp.internal.http.OkHeaders.SELECTED_PROTOCOL; 87e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport static com.squareup.okhttp.internal.http.StatusLine.HTTP_PERM_REDIRECT; 883c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport static com.squareup.okhttp.internal.http.StatusLine.HTTP_TEMP_REDIRECT; 89166772be0e5cfdaea1a64b9f63e4c8dbfe48cba3Narayan Kamathimport static com.squareup.okhttp.mockwebserver.SocketPolicy.DISCONNECT_AT_END; 90166772be0e5cfdaea1a64b9f63e4c8dbfe48cba3Narayan Kamathimport static com.squareup.okhttp.mockwebserver.SocketPolicy.DISCONNECT_AT_START; 91166772be0e5cfdaea1a64b9f63e4c8dbfe48cba3Narayan Kamathimport static com.squareup.okhttp.mockwebserver.SocketPolicy.SHUTDOWN_INPUT_AT_END; 92166772be0e5cfdaea1a64b9f63e4c8dbfe48cba3Narayan Kamathimport static com.squareup.okhttp.mockwebserver.SocketPolicy.SHUTDOWN_OUTPUT_AT_END; 933c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport static java.util.concurrent.TimeUnit.MILLISECONDS; 943c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport static java.util.concurrent.TimeUnit.NANOSECONDS; 952231db3e6bb54447a9b14cf004a6cb03c373651cjwilsonimport static org.junit.Assert.assertEquals; 962231db3e6bb54447a9b14cf004a6cb03c373651cjwilsonimport static org.junit.Assert.assertFalse; 973c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport static org.junit.Assert.assertNotNull; 982231db3e6bb54447a9b14cf004a6cb03c373651cjwilsonimport static org.junit.Assert.assertNull; 992231db3e6bb54447a9b14cf004a6cb03c373651cjwilsonimport static org.junit.Assert.assertTrue; 1002231db3e6bb54447a9b14cf004a6cb03c373651cjwilsonimport static org.junit.Assert.fail; 101c3f6f16bd4a2338e88275641b9f2f56e816ca377Narayan Kamath 10254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson/** Android's URLConnectionTest. */ 1032231db3e6bb54447a9b14cf004a6cb03c373651cjwilsonpublic final class URLConnectionTest { 10471b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller @Rule public final MockWebServer server = new MockWebServer(); 10571b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller @Rule public final MockWebServer server2 = new MockWebServer(); 106e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Rule public final TemporaryFolder tempDir = new TemporaryFolder(); 10754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 10871b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller private SSLContext sslContext = SslContextBuilder.localhost(); 109e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller private OkUrlFactory client; 1103c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller private HttpURLConnection connection; 111e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller private Cache cache; 11254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 11354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Before public void setUp() throws Exception { 11471b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller server.setProtocolNegotiationEnabled(false); 115e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client = new OkUrlFactory(new OkHttpClient()); 11654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 11754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 11854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @After public void tearDown() throws Exception { 119166772be0e5cfdaea1a64b9f63e4c8dbfe48cba3Narayan Kamath Authenticator.setDefault(null); 12054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson System.clearProperty("proxyHost"); 12154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson System.clearProperty("proxyPort"); 122e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller System.clearProperty("http.agent"); 12354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson System.clearProperty("http.proxyHost"); 12454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson System.clearProperty("http.proxyPort"); 12554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson System.clearProperty("https.proxyHost"); 12654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson System.clearProperty("https.proxyPort"); 12754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson if (cache != null) { 128faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath cache.delete(); 12954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 13054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 13154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 13254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void requestHeaders() throws IOException, InterruptedException { 13354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse()); 13454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 1353c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/")); 1363c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection.addRequestProperty("D", "e"); 1373c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection.addRequestProperty("D", "f"); 1383c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals("f", connection.getRequestProperty("D")); 1393c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals("f", connection.getRequestProperty("d")); 1403c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller Map<String, List<String>> requestHeaders = connection.getRequestProperties(); 14171b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller assertEquals(newSet("e", "f"), new LinkedHashSet<>(requestHeaders.get("D"))); 14271b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller assertEquals(newSet("e", "f"), new LinkedHashSet<>(requestHeaders.get("d"))); 14354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson try { 14454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson requestHeaders.put("G", Arrays.asList("h")); 14554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson fail("Modified an unmodifiable view."); 14654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } catch (UnsupportedOperationException expected) { 14754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 14854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson try { 14954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson requestHeaders.get("D").add("i"); 15054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson fail("Modified an unmodifiable view."); 15154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } catch (UnsupportedOperationException expected) { 15254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 15354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson try { 1543c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection.setRequestProperty(null, "j"); 15554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson fail(); 15654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } catch (NullPointerException expected) { 15754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 15854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson try { 1593c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection.addRequestProperty(null, "k"); 16054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson fail(); 16154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } catch (NullPointerException expected) { 16254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 1633c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection.setRequestProperty("NullValue", null); 1643c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertNull(connection.getRequestProperty("NullValue")); 1653c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection.addRequestProperty("AnotherNullValue", null); 1663c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertNull(connection.getRequestProperty("AnotherNullValue")); 16754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 1683c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection.getResponseCode(); 16954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson RecordedRequest request = server.takeRequest(); 170e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(Arrays.asList("e", "f"), request.getHeaders().values("D")); 171e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertNull(request.getHeader("NullValue")); 172e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertNull(request.getHeader("AnotherNullValue")); 173e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertNull(request.getHeader("G")); 174e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertNull(request.getHeader("null")); 17554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 17654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson try { 1773c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection.addRequestProperty("N", "o"); 17854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson fail("Set header after connect"); 17954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } catch (IllegalStateException expected) { 18054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 18154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson try { 1823c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection.setRequestProperty("P", "q"); 18354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson fail("Set header after connect"); 18454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } catch (IllegalStateException expected) { 18554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 18654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson try { 1873c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection.getRequestProperties(); 18854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson fail(); 18954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } catch (IllegalStateException expected) { 19054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 19154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 19254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 19354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void getRequestPropertyReturnsLastValue() throws Exception { 1943c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/")); 1953c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection.addRequestProperty("A", "value1"); 1963c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection.addRequestProperty("A", "value2"); 1973c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals("value2", connection.getRequestProperty("A")); 19854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 19954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 20054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void responseHeaders() throws IOException, InterruptedException { 20154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse().setStatus("HTTP/1.0 200 Fantastic") 20254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson .addHeader("A: c") 20354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson .addHeader("B: d") 20454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson .addHeader("A: e") 20554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson .setChunkedBody("ABCDE\nFGHIJ\nKLMNO\nPQR", 8)); 20654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 2073c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/")); 2083c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals(200, connection.getResponseCode()); 2093c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals("Fantastic", connection.getResponseMessage()); 2103c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals("HTTP/1.0 200 Fantastic", connection.getHeaderField(null)); 2113c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller Map<String, List<String>> responseHeaders = connection.getHeaderFields(); 21254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals(Arrays.asList("HTTP/1.0 200 Fantastic"), responseHeaders.get(null)); 21371b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller assertEquals(newSet("c", "e"), new LinkedHashSet<>(responseHeaders.get("A"))); 21471b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller assertEquals(newSet("c", "e"), new LinkedHashSet<>(responseHeaders.get("a"))); 21554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson try { 21654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson responseHeaders.put("N", Arrays.asList("o")); 21754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson fail("Modified an unmodifiable view."); 21854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } catch (UnsupportedOperationException expected) { 21954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 22054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson try { 22154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson responseHeaders.get("A").add("f"); 22254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson fail("Modified an unmodifiable view."); 22354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } catch (UnsupportedOperationException expected) { 22454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 2253c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals("A", connection.getHeaderFieldKey(0)); 2263c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals("c", connection.getHeaderField(0)); 2273c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals("B", connection.getHeaderFieldKey(1)); 2283c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals("d", connection.getHeaderField(1)); 2293c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals("A", connection.getHeaderFieldKey(2)); 2303c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals("e", connection.getHeaderField(2)); 2316c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer connection.getInputStream().close(); 23254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 23354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 23454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void serverSendsInvalidResponseHeaders() throws Exception { 23554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse().setStatus("HTP/1.1 200 OK")); 23654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 2373c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/")); 23854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson try { 2393c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection.getResponseCode(); 24054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson fail(); 24154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } catch (IOException expected) { 24254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 24354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 24454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 24554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void serverSendsInvalidCodeTooLarge() throws Exception { 24654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse().setStatus("HTTP/1.1 2147483648 OK")); 24754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 2483c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/")); 24954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson try { 2503c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection.getResponseCode(); 25154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson fail(); 25254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } catch (IOException expected) { 25354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 25454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 25554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 25654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void serverSendsInvalidCodeNotANumber() throws Exception { 25754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse().setStatus("HTTP/1.1 00a OK")); 25854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 2593c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/")); 26054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson try { 2613c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection.getResponseCode(); 26254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson fail(); 26354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } catch (IOException expected) { 26454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 26554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 26654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 26754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void serverSendsUnnecessaryWhitespace() throws Exception { 26854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse().setStatus(" HTTP/1.1 2147483648 OK")); 26954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 2703c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/")); 27154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson try { 2723c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection.getResponseCode(); 27354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson fail(); 27454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } catch (IOException expected) { 27554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 27654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 27754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 27854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void connectRetriesUntilConnectedOrFailed() throws Exception { 27954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson URL url = server.getUrl("/foo"); 28071b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller server.shutdown(); 28154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 2823c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(url); 28354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson try { 28454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson connection.connect(); 28554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson fail(); 28654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } catch (IOException expected) { 28754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 28854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 28954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 29054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void requestBodySurvivesRetriesWithFixedLength() throws Exception { 29154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson testRequestBodySurvivesRetries(TransferKind.FIXED_LENGTH); 29254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 29354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 29454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void requestBodySurvivesRetriesWithChunkedStreaming() throws Exception { 29554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson testRequestBodySurvivesRetries(TransferKind.CHUNKED); 29654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 29754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 29854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void requestBodySurvivesRetriesWithBufferedBody() throws Exception { 29954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson testRequestBodySurvivesRetries(TransferKind.END_OF_STREAM); 30054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 30154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 30254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson private void testRequestBodySurvivesRetries(TransferKind transferKind) throws Exception { 30354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse().setBody("abc")); 30454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 30554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson // Use a misconfigured proxy to guarantee that the request is retried. 30654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson FakeProxySelector proxySelector = new FakeProxySelector(); 30771b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller proxySelector.proxies.add(server2.toProxyAddress()); 308e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setProxySelector(proxySelector); 30971b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller server2.shutdown(); 31054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 3113c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/def")); 31254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson connection.setDoOutput(true); 31354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson transferKind.setForRequest(connection, 4); 31454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson connection.getOutputStream().write("body".getBytes("UTF-8")); 31554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertContent("abc", connection); 31654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 317e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("body", server.takeRequest().getBody().readUtf8()); 31854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 31954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 32054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void getErrorStreamOnSuccessfulRequest() throws Exception { 32154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse().setBody("A")); 3223c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/")); 32354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertNull(connection.getErrorStream()); 3246c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer connection.getInputStream().close(); 32554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 32654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 32754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void getErrorStreamOnUnsuccessfulRequest() throws Exception { 32854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse().setResponseCode(404).setBody("A")); 3293c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/")); 33054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals("A", readAscii(connection.getErrorStream(), Integer.MAX_VALUE)); 33154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 33254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 33354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson // Check that if we don't read to the end of a response, the next request on the 33454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson // recycled connection doesn't get the unread tail of the first request's response. 33554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson // http://code.google.com/p/android/issues/detail?id=2939 33654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void bug2939() throws Exception { 33754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson MockResponse response = new MockResponse().setChunkedBody("ABCDE\nFGHIJ\nKLMNO\nPQR", 8); 33854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 33954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(response); 34054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(response); 34154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 3426c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer HttpURLConnection c1 = client.open(server.getUrl("/")); 3436c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer assertContent("ABCDE", c1, 5); 3446c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer HttpURLConnection c2 = client.open(server.getUrl("/")); 3456c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer assertContent("ABCDE", c2, 5); 3466c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer 3476c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer c1.getInputStream().close(); 3486c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer c2.getInputStream().close(); 34954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 35054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 35154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson // Check that we recognize a few basic mime types by extension. 35254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson // http://code.google.com/p/android/issues/detail?id=10100 35354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void bug10100() throws Exception { 35454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals("image/jpeg", URLConnection.guessContentTypeFromName("someFile.jpg")); 35554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals("application/pdf", URLConnection.guessContentTypeFromName("stuff.pdf")); 35654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 35754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 35854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void connectionsArePooled() throws Exception { 35954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson MockResponse response = new MockResponse().setBody("ABCDEFGHIJKLMNOPQR"); 36054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 36154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(response); 36254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(response); 36354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(response); 36454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 36554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertContent("ABCDEFGHIJKLMNOPQR", client.open(server.getUrl("/foo"))); 36654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals(0, server.takeRequest().getSequenceNumber()); 36754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertContent("ABCDEFGHIJKLMNOPQR", client.open(server.getUrl("/bar?baz=quux"))); 36854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals(1, server.takeRequest().getSequenceNumber()); 36954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertContent("ABCDEFGHIJKLMNOPQR", client.open(server.getUrl("/z"))); 37054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals(2, server.takeRequest().getSequenceNumber()); 37154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 37254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 37354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void chunkedConnectionsArePooled() throws Exception { 37454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson MockResponse response = new MockResponse().setChunkedBody("ABCDEFGHIJKLMNOPQR", 5); 37554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 37654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(response); 37754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(response); 37854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(response); 37954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 38054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertContent("ABCDEFGHIJKLMNOPQR", client.open(server.getUrl("/foo"))); 38154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals(0, server.takeRequest().getSequenceNumber()); 38254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertContent("ABCDEFGHIJKLMNOPQR", client.open(server.getUrl("/bar?baz=quux"))); 38354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals(1, server.takeRequest().getSequenceNumber()); 38454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertContent("ABCDEFGHIJKLMNOPQR", client.open(server.getUrl("/z"))); 38554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals(2, server.takeRequest().getSequenceNumber()); 38654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 38754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 38854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void serverClosesSocket() throws Exception { 38954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson testServerClosesOutput(DISCONNECT_AT_END); 39054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 39154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 39254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void serverShutdownInput() throws Exception { 39354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson testServerClosesOutput(SHUTDOWN_INPUT_AT_END); 39454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 39554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 39654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void serverShutdownOutput() throws Exception { 39754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson testServerClosesOutput(SHUTDOWN_OUTPUT_AT_END); 39854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 39954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 4003c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Test public void invalidHost() throws Exception { 4013c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller // Note that 1234.1.1.1 is an invalid host in a URI, but URL isn't as strict. 4023c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller URL url = new URL("http://1234.1.1.1/index.html"); 4033c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller HttpURLConnection connection = client.open(url); 4043c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller try { 4053c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection.connect(); 4063c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller fail(); 407ca342d6c3c54ae2417d4e61c925ba6f63b31a571jwilson } catch (UnknownHostException expected) { 4083c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 4093c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 4103c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 41154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson private void testServerClosesOutput(SocketPolicy socketPolicy) throws Exception { 41254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse().setBody("This connection won't pool properly") 41354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson .setSocketPolicy(socketPolicy)); 41454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson MockResponse responseAfter = new MockResponse().setBody("This comes after a busted connection"); 41554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(responseAfter); 41654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(responseAfter); // Enqueue 2x because the broken connection may be reused. 41754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 41854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson HttpURLConnection connection1 = client.open(server.getUrl("/a")); 41954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson connection1.setReadTimeout(100); 42054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertContent("This connection won't pool properly", connection1); 42154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals(0, server.takeRequest().getSequenceNumber()); 42254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson HttpURLConnection connection2 = client.open(server.getUrl("/b")); 42354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson connection2.setReadTimeout(100); 42454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertContent("This comes after a busted connection", connection2); 42554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 42654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson // Check that a fresh connection was created, either immediately or after attempting reuse. 42754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson RecordedRequest requestAfter = server.takeRequest(); 42854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson if (server.getRequestCount() == 3) { 42954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson requestAfter = server.takeRequest(); // The failure consumed a response. 43054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 43154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson // sequence number 0 means the HTTP socket connection was not reused 43254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals(0, requestAfter.getSequenceNumber()); 43354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 43454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 43554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson enum WriteKind {BYTE_BY_BYTE, SMALL_BUFFERS, LARGE_BUFFERS} 43654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 43754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void chunkedUpload_byteByByte() throws Exception { 43854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson doUpload(TransferKind.CHUNKED, WriteKind.BYTE_BY_BYTE); 43954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 44054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 44154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void chunkedUpload_smallBuffers() throws Exception { 44254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson doUpload(TransferKind.CHUNKED, WriteKind.SMALL_BUFFERS); 44354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 44454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 44554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void chunkedUpload_largeBuffers() throws Exception { 44654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson doUpload(TransferKind.CHUNKED, WriteKind.LARGE_BUFFERS); 44754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 44854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 44954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void fixedLengthUpload_byteByByte() throws Exception { 45054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson doUpload(TransferKind.FIXED_LENGTH, WriteKind.BYTE_BY_BYTE); 45154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 45254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 45354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void fixedLengthUpload_smallBuffers() throws Exception { 45454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson doUpload(TransferKind.FIXED_LENGTH, WriteKind.SMALL_BUFFERS); 45554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 45654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 45754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void fixedLengthUpload_largeBuffers() throws Exception { 45854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson doUpload(TransferKind.FIXED_LENGTH, WriteKind.LARGE_BUFFERS); 45954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 46054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 46154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson private void doUpload(TransferKind uploadKind, WriteKind writeKind) throws Exception { 46254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson int n = 512 * 1024; 46371b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller server.setBodyLimit(0); 46454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse()); 46554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 46654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson HttpURLConnection conn = client.open(server.getUrl("/")); 46754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson conn.setDoOutput(true); 46854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson conn.setRequestMethod("POST"); 46954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson if (uploadKind == TransferKind.CHUNKED) { 47054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson conn.setChunkedStreamingMode(-1); 47154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } else { 47254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson conn.setFixedLengthStreamingMode(n); 47354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 47454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson OutputStream out = conn.getOutputStream(); 47554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson if (writeKind == WriteKind.BYTE_BY_BYTE) { 47654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson for (int i = 0; i < n; ++i) { 47754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson out.write('x'); 47854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 47954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } else { 48054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson byte[] buf = new byte[writeKind == WriteKind.SMALL_BUFFERS ? 256 : 64 * 1024]; 48154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson Arrays.fill(buf, (byte) 'x'); 48254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson for (int i = 0; i < n; i += buf.length) { 48354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson out.write(buf, 0, Math.min(buf.length, n - i)); 48454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 48554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 48654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson out.close(); 48754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals(200, conn.getResponseCode()); 48854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson RecordedRequest request = server.takeRequest(); 48954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals(n, request.getBodySize()); 49054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson if (uploadKind == TransferKind.CHUNKED) { 49154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertTrue(request.getChunkSizes().size() > 0); 49254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } else { 49354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertTrue(request.getChunkSizes().isEmpty()); 49454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 49554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 49654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 49754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void getResponseCodeNoResponseBody() throws Exception { 49854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse().addHeader("abc: def")); 49954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 50054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson URL url = server.getUrl("/"); 50154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson HttpURLConnection conn = client.open(url); 50254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson conn.setDoInput(false); 50354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals("def", conn.getHeaderField("abc")); 50454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals(200, conn.getResponseCode()); 50554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson try { 50654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson conn.getInputStream(); 50754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson fail(); 50854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } catch (ProtocolException expected) { 50954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 51054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 51154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 51254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void connectViaHttps() throws Exception { 51371b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller server.useHttps(sslContext.getSocketFactory(), false); 51454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse().setBody("this response comes via HTTPS")); 51554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 516e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setSslSocketFactory(sslContext.getSocketFactory()); 517e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setHostnameVerifier(new RecordingHostnameVerifier()); 5183c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/foo")); 51954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 52054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertContent("this response comes via HTTPS", connection); 52154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 52254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson RecordedRequest request = server.takeRequest(); 52354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals("GET /foo HTTP/1.1", request.getRequestLine()); 52454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 52554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 5263c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Test public void inspectHandshakeThroughoutRequestLifecycle() throws Exception { 52771b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller server.useHttps(sslContext.getSocketFactory(), false); 5283c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller server.enqueue(new MockResponse()); 5293c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 530e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setSslSocketFactory(sslContext.getSocketFactory()); 531e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setHostnameVerifier(new RecordingHostnameVerifier()); 5323c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 5333c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller HttpsURLConnection httpsConnection = (HttpsURLConnection) client.open(server.getUrl("/foo")); 5343c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 5353c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller // Prior to calling connect(), getting the cipher suite is forbidden. 5363c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller try { 5373c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller httpsConnection.getCipherSuite(); 5383c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller fail(); 5393c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } catch (IllegalStateException expected) { 5403c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 5413c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 5423c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller // Calling connect establishes a handshake... 5433c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller httpsConnection.connect(); 5443c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertNotNull(httpsConnection.getCipherSuite()); 5453c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 5463c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller // ...which remains after we read the response body... 5473c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertContent("", httpsConnection); 5483c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertNotNull(httpsConnection.getCipherSuite()); 5493c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 5503c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller // ...and after we disconnect. 5513c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller httpsConnection.disconnect(); 5523c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertNotNull(httpsConnection.getCipherSuite()); 5533c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 5543c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 55554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void connectViaHttpsReusingConnections() throws IOException, InterruptedException { 55671b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller server.useHttps(sslContext.getSocketFactory(), false); 55754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse().setBody("this response comes via HTTPS")); 55854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse().setBody("another response via HTTPS")); 55954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 56054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson // The pool will only reuse sockets if the SSL socket factories are the same. 56154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson SSLSocketFactory clientSocketFactory = sslContext.getSocketFactory(); 56254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson RecordingHostnameVerifier hostnameVerifier = new RecordingHostnameVerifier(); 56354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 564e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setSslSocketFactory(clientSocketFactory); 565e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setHostnameVerifier(hostnameVerifier); 5663c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/")); 56754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertContent("this response comes via HTTPS", connection); 56854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 56954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson connection = client.open(server.getUrl("/")); 57054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertContent("another response via HTTPS", connection); 57154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 57254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals(0, server.takeRequest().getSequenceNumber()); 57354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals(1, server.takeRequest().getSequenceNumber()); 57454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 57554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 57654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void connectViaHttpsReusingConnectionsDifferentFactories() 57754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson throws IOException, InterruptedException { 57871b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller server.useHttps(sslContext.getSocketFactory(), false); 57954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse().setBody("this response comes via HTTPS")); 58054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse().setBody("another response via HTTPS")); 58154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 58254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson // install a custom SSL socket factory so the server can be authorized 583e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setSslSocketFactory(sslContext.getSocketFactory()); 584e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setHostnameVerifier(new RecordingHostnameVerifier()); 58554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson HttpURLConnection connection1 = client.open(server.getUrl("/")); 58654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertContent("this response comes via HTTPS", connection1); 58754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 588e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setSslSocketFactory(null); 58954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson HttpURLConnection connection2 = client.open(server.getUrl("/")); 59054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson try { 59154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson readAscii(connection2.getInputStream(), Integer.MAX_VALUE); 59254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson fail("without an SSL socket factory, the connection should fail"); 59354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } catch (SSLException expected) { 59454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 59554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 59654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 5977aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller @Test public void connectViaHttpsWithSSLFallback() throws Exception { 59871b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller server.useHttps(sslContext.getSocketFactory(), false); 59954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse().setSocketPolicy(SocketPolicy.FAIL_HANDSHAKE)); 60054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse().setBody("this response comes via SSL")); 60154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 602e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller suppressTlsFallbackScsv(client.client()); 603e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setHostnameVerifier(new RecordingHostnameVerifier()); 6043c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/foo")); 60554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 60654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertContent("this response comes via SSL", connection); 60754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 60854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson RecordedRequest request = server.takeRequest(); 60954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals("GET /foo HTTP/1.1", request.getRequestLine()); 6107aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller assertEquals(TlsVersion.TLS_1_0, request.getTlsVersion()); 6117aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller } 6127aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller 6137aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller @Test public void connectViaHttpsWithSSLFallbackFailuresRecorded() throws Exception { 61471b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller server.useHttps(sslContext.getSocketFactory(), false); 6157aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller server.enqueue(new MockResponse().setSocketPolicy(SocketPolicy.FAIL_HANDSHAKE)); 6167aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller server.enqueue(new MockResponse().setSocketPolicy(SocketPolicy.FAIL_HANDSHAKE)); 6177aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller 6187aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller suppressTlsFallbackScsv(client.client()); 6196c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer client.client().setDns(new SingleInetAddressDns()); 6207aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller 6217aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller client.client().setHostnameVerifier(new RecordingHostnameVerifier()); 6227aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller connection = client.open(server.getUrl("/foo")); 6237aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller 6247aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller try { 6257aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller connection.getResponseCode(); 62671b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller fail(); 62771b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller } catch (IOException expected) { 62871b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller assertEquals(1, expected.getSuppressed().length); 6297aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller } 63054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 63154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 63254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson /** 6333c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * When a pooled connection fails, don't blame the route. Otherwise pooled 6343c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * connection failures can cause unnecessary SSL fallbacks. 6353c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * 6363c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * https://github.com/square/okhttp/issues/515 6373c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller */ 6383c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Test public void sslFallbackNotUsedWhenRecycledConnectionFails() throws Exception { 63971b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller server.useHttps(sslContext.getSocketFactory(), false); 6403c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller server.enqueue(new MockResponse() 6413c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller .setBody("abc") 6423c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller .setSocketPolicy(SocketPolicy.DISCONNECT_AT_END)); 6433c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller server.enqueue(new MockResponse().setBody("def")); 6443c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 645e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller suppressTlsFallbackScsv(client.client()); 646e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setHostnameVerifier(new RecordingHostnameVerifier()); 6473c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 6483c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertContent("abc", client.open(server.getUrl("/"))); 6493c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertContent("def", client.open(server.getUrl("/"))); 6503c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 651e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Set<TlsVersion> tlsVersions = 652e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller EnumSet.of(TlsVersion.TLS_1_0, TlsVersion.TLS_1_2); // v1.2 on OpenJDK 8. 653e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 6543c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller RecordedRequest request1 = server.takeRequest(); 655e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertTrue(tlsVersions.contains(request1.getTlsVersion())); 6563c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 6573c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller RecordedRequest request2 = server.takeRequest(); 658e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertTrue(tlsVersions.contains(request2.getTlsVersion())); 6593c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 6603c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 6613c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller /** 66254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson * Verify that we don't retry connections on certificate verification errors. 66354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson * 66454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson * http://code.google.com/p/android/issues/detail?id=13178 66554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson */ 66654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void connectViaHttpsToUntrustedServer() throws IOException, InterruptedException { 66771b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller server.useHttps(sslContext.getSocketFactory(), false); 66854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse()); // unused 66954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 6703c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/foo")); 67154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson try { 67254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson connection.getInputStream(); 67354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson fail(); 67454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } catch (SSLHandshakeException expected) { 67554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertTrue(expected.getCause() instanceof CertificateException); 67654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 67754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals(0, server.getRequestCount()); 67854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 67954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 68054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void connectViaProxyUsingProxyArg() throws Exception { 68154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson testConnectViaProxy(ProxyConfig.CREATE_ARG); 68254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 68354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 68454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void connectViaProxyUsingProxySystemProperty() throws Exception { 68554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson testConnectViaProxy(ProxyConfig.PROXY_SYSTEM_PROPERTY); 68654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 68754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 68854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void connectViaProxyUsingHttpProxySystemProperty() throws Exception { 68954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson testConnectViaProxy(ProxyConfig.HTTP_PROXY_SYSTEM_PROPERTY); 69054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 69154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 69254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson private void testConnectViaProxy(ProxyConfig proxyConfig) throws Exception { 69354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson MockResponse mockResponse = new MockResponse().setBody("this response comes via a proxy"); 69454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(mockResponse); 69554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 696078ce1ecb0917cbf08ab74325e6fe1fa6474c2a7Tobias Thierer URL url = new URL("http://android.com/foo"); 69771b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller connection = proxyConfig.connect(server, client, url); 69854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertContent("this response comes via a proxy", connection); 6993c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertTrue(connection.usingProxy()); 70054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 70171b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller RecordedRequest request = server.takeRequest(); 702078ce1ecb0917cbf08ab74325e6fe1fa6474c2a7Tobias Thierer assertEquals("GET http://android.com/foo HTTP/1.1", request.getRequestLine()); 703078ce1ecb0917cbf08ab74325e6fe1fa6474c2a7Tobias Thierer assertEquals("android.com", request.getHeader("Host")); 70454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 70554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 70671b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller @Test public void contentDisagreesWithContentLengthHeaderBodyTooLong() throws IOException { 70754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse().setBody("abc\r\nYOU SHOULD NOT SEE THIS") 70854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson .clearHeaders() 70954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson .addHeader("Content-Length: 3")); 71054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertContent("abc", client.open(server.getUrl("/"))); 71154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 71254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 71371b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller @Test public void contentDisagreesWithContentLengthHeaderBodyTooShort() throws IOException { 71471b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller server.enqueue(new MockResponse().setBody("abc") 71571b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller .setHeader("Content-Length", "5") 71671b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller .setSocketPolicy(SocketPolicy.DISCONNECT_AT_END)); 71771b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller try { 71871b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller readAscii(client.open(server.getUrl("/")).getInputStream(), 5); 71971b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller fail(); 72071b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller } catch (ProtocolException expected) { 72171b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller } 72271b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller } 72371b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller 724a83ddf194ffbae04ce536967efff0ec72df70e10Lorenzo Colitti public void testConnectViaSocketFactory(boolean useHttps) throws IOException { 725a83ddf194ffbae04ce536967efff0ec72df70e10Lorenzo Colitti SocketFactory uselessSocketFactory = new SocketFactory() { 726a83ddf194ffbae04ce536967efff0ec72df70e10Lorenzo Colitti public Socket createSocket() { throw new IllegalArgumentException("useless"); } 727a83ddf194ffbae04ce536967efff0ec72df70e10Lorenzo Colitti public Socket createSocket(InetAddress host, int port) { return null; } 728a83ddf194ffbae04ce536967efff0ec72df70e10Lorenzo Colitti public Socket createSocket(InetAddress address, int port, InetAddress localAddress, 729a83ddf194ffbae04ce536967efff0ec72df70e10Lorenzo Colitti int localPort) { return null; } 730a83ddf194ffbae04ce536967efff0ec72df70e10Lorenzo Colitti public Socket createSocket(String host, int port) { return null; } 731a83ddf194ffbae04ce536967efff0ec72df70e10Lorenzo Colitti public Socket createSocket(String host, int port, InetAddress localHost, int localPort) { 732a83ddf194ffbae04ce536967efff0ec72df70e10Lorenzo Colitti return null; 733a83ddf194ffbae04ce536967efff0ec72df70e10Lorenzo Colitti } 734a83ddf194ffbae04ce536967efff0ec72df70e10Lorenzo Colitti }; 735a83ddf194ffbae04ce536967efff0ec72df70e10Lorenzo Colitti 736a83ddf194ffbae04ce536967efff0ec72df70e10Lorenzo Colitti if (useHttps) { 73771b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller server.useHttps(sslContext.getSocketFactory(), false); 738e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setSslSocketFactory(sslContext.getSocketFactory()); 739e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setHostnameVerifier(new RecordingHostnameVerifier()); 740a83ddf194ffbae04ce536967efff0ec72df70e10Lorenzo Colitti } 741a83ddf194ffbae04ce536967efff0ec72df70e10Lorenzo Colitti 742a83ddf194ffbae04ce536967efff0ec72df70e10Lorenzo Colitti server.enqueue(new MockResponse().setStatus("HTTP/1.1 200 OK")); 743a83ddf194ffbae04ce536967efff0ec72df70e10Lorenzo Colitti 744e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setSocketFactory(uselessSocketFactory); 745a83ddf194ffbae04ce536967efff0ec72df70e10Lorenzo Colitti connection = client.open(server.getUrl("/")); 746a83ddf194ffbae04ce536967efff0ec72df70e10Lorenzo Colitti try { 747a83ddf194ffbae04ce536967efff0ec72df70e10Lorenzo Colitti connection.getResponseCode(); 748a83ddf194ffbae04ce536967efff0ec72df70e10Lorenzo Colitti fail(); 749a83ddf194ffbae04ce536967efff0ec72df70e10Lorenzo Colitti } catch (IllegalArgumentException expected) { 750a83ddf194ffbae04ce536967efff0ec72df70e10Lorenzo Colitti } 751a83ddf194ffbae04ce536967efff0ec72df70e10Lorenzo Colitti 752e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setSocketFactory(SocketFactory.getDefault()); 753a83ddf194ffbae04ce536967efff0ec72df70e10Lorenzo Colitti connection = client.open(server.getUrl("/")); 754a83ddf194ffbae04ce536967efff0ec72df70e10Lorenzo Colitti assertEquals(200, connection.getResponseCode()); 755a83ddf194ffbae04ce536967efff0ec72df70e10Lorenzo Colitti } 756a83ddf194ffbae04ce536967efff0ec72df70e10Lorenzo Colitti 757a83ddf194ffbae04ce536967efff0ec72df70e10Lorenzo Colitti @Test public void connectHttpViaSocketFactory() throws Exception { 758a83ddf194ffbae04ce536967efff0ec72df70e10Lorenzo Colitti testConnectViaSocketFactory(false); 759a83ddf194ffbae04ce536967efff0ec72df70e10Lorenzo Colitti } 760a83ddf194ffbae04ce536967efff0ec72df70e10Lorenzo Colitti 761a83ddf194ffbae04ce536967efff0ec72df70e10Lorenzo Colitti @Test public void connectHttpsViaSocketFactory() throws Exception { 762a83ddf194ffbae04ce536967efff0ec72df70e10Lorenzo Colitti testConnectViaSocketFactory(true); 763a83ddf194ffbae04ce536967efff0ec72df70e10Lorenzo Colitti } 764a83ddf194ffbae04ce536967efff0ec72df70e10Lorenzo Colitti 76571b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller @Test public void contentDisagreesWithChunkedHeaderBodyTooLong() throws IOException { 76654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson MockResponse mockResponse = new MockResponse(); 76754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson mockResponse.setChunkedBody("abc", 3); 768e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Buffer buffer = mockResponse.getBody(); 769e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller buffer.writeUtf8("\r\nYOU SHOULD NOT SEE THIS"); 770e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller mockResponse.setBody(buffer); 77154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson mockResponse.clearHeaders(); 77254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson mockResponse.addHeader("Transfer-encoding: chunked"); 77354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 77454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(mockResponse); 77554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 77654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertContent("abc", client.open(server.getUrl("/"))); 77754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 77854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 77971b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller @Test public void contentDisagreesWithChunkedHeaderBodyTooShort() throws IOException { 78071b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller MockResponse mockResponse = new MockResponse(); 78171b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller mockResponse.setChunkedBody("abcde", 5); 78271b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller 78371b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller Buffer truncatedBody = new Buffer(); 78471b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller Buffer fullBody = mockResponse.getBody(); 78571b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller truncatedBody.write(fullBody, fullBody.indexOf((byte) 'e')); 78671b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller mockResponse.setBody(truncatedBody); 78771b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller 78871b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller mockResponse.clearHeaders(); 78971b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller mockResponse.addHeader("Transfer-encoding: chunked"); 79071b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller mockResponse.setSocketPolicy(SocketPolicy.DISCONNECT_AT_END); 79171b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller 79271b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller server.enqueue(mockResponse); 79371b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller 79471b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller try { 79571b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller readAscii(client.open(server.getUrl("/")).getInputStream(), 5); 79671b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller fail(); 79771b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller } catch (ProtocolException expected) { 79871b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller } 79971b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller } 80071b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller 80154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void connectViaHttpProxyToHttpsUsingProxyArgWithNoProxy() throws Exception { 80254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson testConnectViaDirectProxyToHttps(ProxyConfig.NO_PROXY); 80354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 80454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 80554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void connectViaHttpProxyToHttpsUsingHttpProxySystemProperty() throws Exception { 80654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson // https should not use http proxy 80754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson testConnectViaDirectProxyToHttps(ProxyConfig.HTTP_PROXY_SYSTEM_PROPERTY); 80854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 80954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 81054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson private void testConnectViaDirectProxyToHttps(ProxyConfig proxyConfig) throws Exception { 81171b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller server.useHttps(sslContext.getSocketFactory(), false); 81254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse().setBody("this response comes via HTTPS")); 81354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 81454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson URL url = server.getUrl("/foo"); 815e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setSslSocketFactory(sslContext.getSocketFactory()); 816e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setHostnameVerifier(new RecordingHostnameVerifier()); 81771b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller connection = proxyConfig.connect(server, client, url); 81854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 81954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertContent("this response comes via HTTPS", connection); 82054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 82154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson RecordedRequest request = server.takeRequest(); 82254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals("GET /foo HTTP/1.1", request.getRequestLine()); 82354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 82454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 82554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void connectViaHttpProxyToHttpsUsingProxyArg() throws Exception { 82654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson testConnectViaHttpProxyToHttps(ProxyConfig.CREATE_ARG); 82754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 82854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 82954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson /** 83054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson * We weren't honoring all of the appropriate proxy system properties when 83154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson * connecting via HTTPS. http://b/3097518 83254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson */ 83354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void connectViaHttpProxyToHttpsUsingProxySystemProperty() throws Exception { 83454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson testConnectViaHttpProxyToHttps(ProxyConfig.PROXY_SYSTEM_PROPERTY); 83554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 83654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 83754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void connectViaHttpProxyToHttpsUsingHttpsProxySystemProperty() throws Exception { 83854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson testConnectViaHttpProxyToHttps(ProxyConfig.HTTPS_PROXY_SYSTEM_PROPERTY); 83954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 84054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 84154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson /** 84254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson * We were verifying the wrong hostname when connecting to an HTTPS site 84354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson * through a proxy. http://b/3097277 84454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson */ 84554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson private void testConnectViaHttpProxyToHttps(ProxyConfig proxyConfig) throws Exception { 84654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson RecordingHostnameVerifier hostnameVerifier = new RecordingHostnameVerifier(); 84754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 84871b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller server.useHttps(sslContext.getSocketFactory(), true); 84954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue( 85054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson new MockResponse().setSocketPolicy(SocketPolicy.UPGRADE_TO_SSL_AT_END).clearHeaders()); 85154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse().setBody("this response comes via a secure proxy")); 85254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 85354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson URL url = new URL("https://android.com/foo"); 854e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setSslSocketFactory(sslContext.getSocketFactory()); 855e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setHostnameVerifier(hostnameVerifier); 85671b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller connection = proxyConfig.connect(server, client, url); 85754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 85854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertContent("this response comes via a secure proxy", connection); 85954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 86054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson RecordedRequest connect = server.takeRequest(); 86154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals("Connect line failure on proxy", "CONNECT android.com:443 HTTP/1.1", 86254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson connect.getRequestLine()); 863eaf55917fcd2f118e26d6b31dcaf9fb8f3ad0d1fjwilson assertEquals("android.com:443", connect.getHeader("Host")); 86454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 86554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson RecordedRequest get = server.takeRequest(); 86654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals("GET /foo HTTP/1.1", get.getRequestLine()); 867e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("android.com", get.getHeader("Host")); 86854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals(Arrays.asList("verify android.com"), hostnameVerifier.calls); 86954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 87054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 871e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller /** Tolerate bad https proxy response when using HttpResponseCache. Android bug 6754912. */ 87254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void connectViaHttpProxyToHttpsUsingBadProxyAndHttpResponseCache() throws Exception { 87354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson initResponseCache(); 87454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 87571b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller server.useHttps(sslContext.getSocketFactory(), true); 876e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // The inclusion of a body in the response to a CONNECT is key to reproducing b/6754912. 877e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller MockResponse badProxyResponse = new MockResponse() 87854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson .setSocketPolicy(SocketPolicy.UPGRADE_TO_SSL_AT_END) 87954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson .setBody("bogus proxy connect response content"); 880e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(badProxyResponse); 881e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse().setBody("response")); 88254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 883e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // Configure a single IP address for the host and a single configuration, so we only need one 884e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // failure to fail permanently. 8856c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer client.client().setDns(new SingleInetAddressDns()); 886e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setSslSocketFactory(sslContext.getSocketFactory()); 887e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setConnectionSpecs(Util.immutableList(ConnectionSpec.MODERN_TLS)); 888e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setHostnameVerifier(new RecordingHostnameVerifier()); 88971b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller client.client().setProxy(server.toProxyAddress()); 89054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 89154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson URL url = new URL("https://android.com/foo"); 8923c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(url); 893e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertContent("response", connection); 89454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 89554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson RecordedRequest connect = server.takeRequest(); 896e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("CONNECT android.com:443 HTTP/1.1", connect.getRequestLine()); 897eaf55917fcd2f118e26d6b31dcaf9fb8f3ad0d1fjwilson assertEquals("android.com:443", connect.getHeader("Host")); 89854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 89954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 90054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson private void initResponseCache() throws IOException { 901e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller cache = new Cache(tempDir.getRoot(), Integer.MAX_VALUE); 902e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setCache(cache); 90354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 90454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 90554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson /** Test which headers are sent unencrypted to the HTTP proxy. */ 90654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void proxyConnectIncludesProxyHeadersOnly() 90754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson throws IOException, InterruptedException { 90854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson RecordingHostnameVerifier hostnameVerifier = new RecordingHostnameVerifier(); 90954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 91071b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller server.useHttps(sslContext.getSocketFactory(), true); 91154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue( 91254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson new MockResponse().setSocketPolicy(SocketPolicy.UPGRADE_TO_SSL_AT_END).clearHeaders()); 91354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse().setBody("encrypted response from the origin server")); 914e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 91571b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller client.client().setProxy(server.toProxyAddress()); 91654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 91754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson URL url = new URL("https://android.com/foo"); 918e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setSslSocketFactory(sslContext.getSocketFactory()); 919e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setHostnameVerifier(hostnameVerifier); 9203c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(url); 92154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson connection.addRequestProperty("Private", "Secret"); 92254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson connection.addRequestProperty("Proxy-Authorization", "bar"); 92354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson connection.addRequestProperty("User-Agent", "baz"); 92454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertContent("encrypted response from the origin server", connection); 92554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 92654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson RecordedRequest connect = server.takeRequest(); 927e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertNull(connect.getHeader("Private")); 9286c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer assertNull(connect.getHeader("Proxy-Authorization")); 9296c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer assertEquals(Version.userAgent(), connect.getHeader("User-Agent")); 930eaf55917fcd2f118e26d6b31dcaf9fb8f3ad0d1fjwilson assertEquals("android.com:443", connect.getHeader("Host")); 931e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("Keep-Alive", connect.getHeader("Proxy-Connection")); 93254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 93354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson RecordedRequest get = server.takeRequest(); 934e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("Secret", get.getHeader("Private")); 93554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals(Arrays.asList("verify android.com"), hostnameVerifier.calls); 93654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 93754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 93854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void proxyAuthenticateOnConnect() throws Exception { 93954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson Authenticator.setDefault(new RecordingAuthenticator()); 94071b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller server.useHttps(sslContext.getSocketFactory(), true); 94154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse().setResponseCode(407) 94254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson .addHeader("Proxy-Authenticate: Basic realm=\"localhost\"")); 94354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue( 94454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson new MockResponse().setSocketPolicy(SocketPolicy.UPGRADE_TO_SSL_AT_END).clearHeaders()); 94554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse().setBody("A")); 946e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 94771b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller client.client().setProxy(server.toProxyAddress()); 94854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 94954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson URL url = new URL("https://android.com/foo"); 950e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setSslSocketFactory(sslContext.getSocketFactory()); 951e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setHostnameVerifier(new RecordingHostnameVerifier()); 9523c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(url); 95354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertContent("A", connection); 95454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 95554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson RecordedRequest connect1 = server.takeRequest(); 95654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals("CONNECT android.com:443 HTTP/1.1", connect1.getRequestLine()); 957e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertNull(connect1.getHeader("Proxy-Authorization")); 95854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 95954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson RecordedRequest connect2 = server.takeRequest(); 96054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals("CONNECT android.com:443 HTTP/1.1", connect2.getRequestLine()); 961e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("Basic " + RecordingAuthenticator.BASE_64_CREDENTIALS, 962e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller connect2.getHeader("Proxy-Authorization")); 96354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 96454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson RecordedRequest get = server.takeRequest(); 96554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals("GET /foo HTTP/1.1", get.getRequestLine()); 966e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertNull(get.getHeader("Proxy-Authorization")); 96754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 96854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 96954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson // Don't disconnect after building a tunnel with CONNECT 97054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson // http://code.google.com/p/android/issues/detail?id=37221 97154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void proxyWithConnectionClose() throws IOException { 97271b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller server.useHttps(sslContext.getSocketFactory(), true); 97354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue( 97454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson new MockResponse().setSocketPolicy(SocketPolicy.UPGRADE_TO_SSL_AT_END).clearHeaders()); 97554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse().setBody("this response comes via a proxy")); 976e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 97771b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller client.client().setProxy(server.toProxyAddress()); 97854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 97954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson URL url = new URL("https://android.com/foo"); 980e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setSslSocketFactory(sslContext.getSocketFactory()); 981e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setHostnameVerifier(new RecordingHostnameVerifier()); 9823c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(url); 98354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson connection.setRequestProperty("Connection", "close"); 98454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 98554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertContent("this response comes via a proxy", connection); 98654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 98754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 98854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void proxyWithConnectionReuse() throws IOException { 98954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson SSLSocketFactory socketFactory = sslContext.getSocketFactory(); 99054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson RecordingHostnameVerifier hostnameVerifier = new RecordingHostnameVerifier(); 99154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 99271b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller server.useHttps(socketFactory, true); 99354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue( 99454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson new MockResponse().setSocketPolicy(SocketPolicy.UPGRADE_TO_SSL_AT_END).clearHeaders()); 99554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse().setBody("response 1")); 99654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse().setBody("response 2")); 997e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 99871b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller client.client().setProxy(server.toProxyAddress()); 99954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 100054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson URL url = new URL("https://android.com/foo"); 1001e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setSslSocketFactory(socketFactory); 1002e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setHostnameVerifier(hostnameVerifier); 100354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertContent("response 1", client.open(url)); 100454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertContent("response 2", client.open(url)); 100554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 100654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 100754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void disconnectedConnection() throws IOException { 100887ed7244fb53ae2bac9f23c033bbd5f23ac269f8Jesse Wilson server.enqueue(new MockResponse() 100987ed7244fb53ae2bac9f23c033bbd5f23ac269f8Jesse Wilson .throttleBody(2, 100, TimeUnit.MILLISECONDS) 101087ed7244fb53ae2bac9f23c033bbd5f23ac269f8Jesse Wilson .setBody("ABCD")); 101154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 10123c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/")); 101354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson InputStream in = connection.getInputStream(); 101454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals('A', (char) in.read()); 101554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson connection.disconnect(); 101654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson try { 101787ed7244fb53ae2bac9f23c033bbd5f23ac269f8Jesse Wilson // Reading 'B' may succeed if it's buffered. 101887ed7244fb53ae2bac9f23c033bbd5f23ac269f8Jesse Wilson in.read(); 101987ed7244fb53ae2bac9f23c033bbd5f23ac269f8Jesse Wilson 102087ed7244fb53ae2bac9f23c033bbd5f23ac269f8Jesse Wilson // But 'C' shouldn't be buffered (the response is throttled) and this should fail. 102154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson in.read(); 102254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson fail("Expected a connection closed exception"); 102354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } catch (IOException expected) { 102454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 10256c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer in.close(); 102654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 102754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 102854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void disconnectBeforeConnect() throws IOException { 102954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse().setBody("A")); 103054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 10313c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/")); 103254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson connection.disconnect(); 103354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertContent("A", connection); 103454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals(200, connection.getResponseCode()); 103554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 103654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 103754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @SuppressWarnings("deprecation") @Test public void defaultRequestProperty() throws Exception { 103854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson URLConnection.setDefaultRequestProperty("X-testSetDefaultRequestProperty", "A"); 103954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertNull(URLConnection.getDefaultRequestProperty("X-setDefaultRequestProperty")); 104054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 104154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 104254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson /** 104354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson * Reads {@code count} characters from the stream. If the stream is 104454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson * exhausted before {@code count} characters can be read, the remaining 104554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson * characters are returned and the stream is closed. 104654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson */ 104754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson private String readAscii(InputStream in, int count) throws IOException { 104854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson StringBuilder result = new StringBuilder(); 104954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson for (int i = 0; i < count; i++) { 105054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson int value = in.read(); 105154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson if (value == -1) { 1052c3f6f16bd4a2338e88275641b9f2f56e816ca377Narayan Kamath in.close(); 105354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson break; 105454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 105554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson result.append((char) value); 105654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 105754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson return result.toString(); 105854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 105954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 106054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void markAndResetWithContentLengthHeader() throws IOException { 106154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson testMarkAndReset(TransferKind.FIXED_LENGTH); 106254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 106354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 106454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void markAndResetWithChunkedEncoding() throws IOException { 106554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson testMarkAndReset(TransferKind.CHUNKED); 106654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 106754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 106854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void markAndResetWithNoLengthHeaders() throws IOException { 106954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson testMarkAndReset(TransferKind.END_OF_STREAM); 107054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 107154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 107254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson private void testMarkAndReset(TransferKind transferKind) throws IOException { 107354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson MockResponse response = new MockResponse(); 107454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson transferKind.setBody(response, "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 1024); 107554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(response); 107654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(response); 107754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 107854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson InputStream in = client.open(server.getUrl("/")).getInputStream(); 107954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertFalse("This implementation claims to support mark().", in.markSupported()); 108054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson in.mark(5); 108154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals("ABCDE", readAscii(in, 5)); 108254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson try { 108354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson in.reset(); 108454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson fail(); 108554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } catch (IOException expected) { 108654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 108754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals("FGHIJKLMNOPQRSTUVWXYZ", readAscii(in, Integer.MAX_VALUE)); 10886c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer in.close(); 108954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertContent("ABCDEFGHIJKLMNOPQRSTUVWXYZ", client.open(server.getUrl("/"))); 109054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 109154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 109254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson /** 109354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson * We've had a bug where we forget the HTTP response when we see response 109454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson * code 401. This causes a new HTTP request to be issued for every call into 109554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson * the URLConnection. 109654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson */ 109754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void unauthorizedResponseHandling() throws IOException { 109854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson MockResponse response = new MockResponse().addHeader("WWW-Authenticate: challenge") 109954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson .setResponseCode(401) // UNAUTHORIZED 110054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson .setBody("Unauthorized"); 110154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(response); 110254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(response); 110354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(response); 110454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 110554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson URL url = server.getUrl("/"); 110654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson HttpURLConnection conn = client.open(url); 110754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 110854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals(401, conn.getResponseCode()); 110954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals(401, conn.getResponseCode()); 111054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals(401, conn.getResponseCode()); 111154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals(1, server.getRequestCount()); 11126c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer conn.getErrorStream().close(); 111354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 111454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 111554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void nonHexChunkSize() throws IOException { 111654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse().setBody("5\r\nABCDE\r\nG\r\nFGHIJKLMNOPQRSTU\r\n0\r\n\r\n") 111754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson .clearHeaders() 111854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson .addHeader("Transfer-encoding: chunked")); 111954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 112054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson URLConnection connection = client.open(server.getUrl("/")); 112154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson try { 112254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson readAscii(connection.getInputStream(), Integer.MAX_VALUE); 112354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson fail(); 112454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } catch (IOException e) { 112554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 11266c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer connection.getInputStream().close(); 112754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 112854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 1129a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller @Test public void malformedChunkSize() throws IOException { 1130a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller server.enqueue(new MockResponse().setBody("5:x\r\nABCDE\r\n0\r\n\r\n") 1131a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller .clearHeaders() 1132a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller .addHeader("Transfer-encoding: chunked")); 1133a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller 1134a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller URLConnection connection = client.open(server.getUrl("/")); 1135a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller try { 1136a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller readAscii(connection.getInputStream(), Integer.MAX_VALUE); 1137a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller fail(); 1138a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller } catch (IOException e) { 11396c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer } finally { 11406c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer connection.getInputStream().close(); 1141a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller } 1142a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller } 1143a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller 1144a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller @Test public void extensionAfterChunkSize() throws IOException { 1145a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller server.enqueue(new MockResponse().setBody("5;x\r\nABCDE\r\n0\r\n\r\n") 1146a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller .clearHeaders() 1147a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller .addHeader("Transfer-encoding: chunked")); 1148a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller 1149a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller HttpURLConnection connection = client.open(server.getUrl("/")); 1150a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller assertContent("ABCDE", connection); 1151a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller } 1152a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller 115354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void missingChunkBody() throws IOException { 115454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse().setBody("5") 115554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson .clearHeaders() 115654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson .addHeader("Transfer-encoding: chunked") 115754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson .setSocketPolicy(DISCONNECT_AT_END)); 115854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 115954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson URLConnection connection = client.open(server.getUrl("/")); 116054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson try { 116154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson readAscii(connection.getInputStream(), Integer.MAX_VALUE); 116254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson fail(); 116354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } catch (IOException e) { 11646c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer } finally { 11656c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer connection.getInputStream().close(); 116654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 116754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 116854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 116954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson /** 117054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson * This test checks whether connections are gzipped by default. This 117154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson * behavior in not required by the API, so a failure of this test does not 117254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson * imply a bug in the implementation. 117354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson */ 117454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void gzipEncodingEnabledByDefault() throws IOException, InterruptedException { 1175e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 1176e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody(gzip("ABCABCABC")) 117754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson .addHeader("Content-Encoding: gzip")); 117854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 117954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson URLConnection connection = client.open(server.getUrl("/")); 118054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals("ABCABCABC", readAscii(connection.getInputStream(), Integer.MAX_VALUE)); 118154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertNull(connection.getContentEncoding()); 118254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals(-1, connection.getContentLength()); 118354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 118454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson RecordedRequest request = server.takeRequest(); 1185e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("gzip", request.getHeader("Accept-Encoding")); 118654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 118754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 118854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void clientConfiguredGzipContentEncoding() throws Exception { 1189e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Buffer bodyBytes = gzip("ABCDEFGHIJKLMNOPQRSTUVWXYZ"); 119054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse() 119154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson .setBody(bodyBytes) 119254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson .addHeader("Content-Encoding: gzip")); 119354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 119454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson URLConnection connection = client.open(server.getUrl("/")); 119554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson connection.addRequestProperty("Accept-Encoding", "gzip"); 119654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson InputStream gunzippedIn = new GZIPInputStream(connection.getInputStream()); 119754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals("ABCDEFGHIJKLMNOPQRSTUVWXYZ", readAscii(gunzippedIn, Integer.MAX_VALUE)); 1198e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(bodyBytes.size(), connection.getContentLength()); 119954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 120054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson RecordedRequest request = server.takeRequest(); 1201e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("gzip", request.getHeader("Accept-Encoding")); 120254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 120354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 120454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void gzipAndConnectionReuseWithFixedLength() throws Exception { 120554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson testClientConfiguredGzipContentEncodingAndConnectionReuse(TransferKind.FIXED_LENGTH, false); 120654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 120754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 120854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void gzipAndConnectionReuseWithChunkedEncoding() throws Exception { 120954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson testClientConfiguredGzipContentEncodingAndConnectionReuse(TransferKind.CHUNKED, false); 121054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 121154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 121254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void gzipAndConnectionReuseWithFixedLengthAndTls() throws Exception { 121354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson testClientConfiguredGzipContentEncodingAndConnectionReuse(TransferKind.FIXED_LENGTH, true); 121454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 121554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 121654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void gzipAndConnectionReuseWithChunkedEncodingAndTls() throws Exception { 121754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson testClientConfiguredGzipContentEncodingAndConnectionReuse(TransferKind.CHUNKED, true); 121854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 121954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 122054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void clientConfiguredCustomContentEncoding() throws Exception { 122154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse().setBody("ABCDE").addHeader("Content-Encoding: custom")); 122254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 122354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson URLConnection connection = client.open(server.getUrl("/")); 122454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson connection.addRequestProperty("Accept-Encoding", "custom"); 122554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals("ABCDE", readAscii(connection.getInputStream(), Integer.MAX_VALUE)); 122654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 122754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson RecordedRequest request = server.takeRequest(); 1228e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("custom", request.getHeader("Accept-Encoding")); 122954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 123054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 123154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson /** 123254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson * Test a bug where gzip input streams weren't exhausting the input stream, 123354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson * which corrupted the request that followed or prevented connection reuse. 123454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson * http://code.google.com/p/android/issues/detail?id=7059 123554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson * http://code.google.com/p/android/issues/detail?id=38817 123654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson */ 123754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson private void testClientConfiguredGzipContentEncodingAndConnectionReuse(TransferKind transferKind, 123854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson boolean tls) throws Exception { 123954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson if (tls) { 124054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson SSLSocketFactory socketFactory = sslContext.getSocketFactory(); 124154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson RecordingHostnameVerifier hostnameVerifier = new RecordingHostnameVerifier(); 124271b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller server.useHttps(socketFactory, false); 1243e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setSslSocketFactory(socketFactory); 1244e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setHostnameVerifier(hostnameVerifier); 124554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 124654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 124754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson MockResponse responseOne = new MockResponse(); 124854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson responseOne.addHeader("Content-Encoding: gzip"); 1249e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller transferKind.setBody(responseOne, gzip("one (gzipped)"), 5); 125054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(responseOne); 125154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson MockResponse responseTwo = new MockResponse(); 125254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson transferKind.setBody(responseTwo, "two (identity)", 5); 125354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(responseTwo); 125454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 125554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson HttpURLConnection connection1 = client.open(server.getUrl("/")); 125654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson connection1.addRequestProperty("Accept-Encoding", "gzip"); 125754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson InputStream gunzippedIn = new GZIPInputStream(connection1.getInputStream()); 125854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals("one (gzipped)", readAscii(gunzippedIn, Integer.MAX_VALUE)); 125954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals(0, server.takeRequest().getSequenceNumber()); 126054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 126154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson HttpURLConnection connection2 = client.open(server.getUrl("/")); 126254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals("two (identity)", readAscii(connection2.getInputStream(), Integer.MAX_VALUE)); 126354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals(1, server.takeRequest().getSequenceNumber()); 126454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 126554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 1266c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller @Test public void transparentGzipWorksAfterExceptionRecovery() throws Exception { 1267c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller server.enqueue(new MockResponse() 1268c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller .setBody("a") 1269c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller .setSocketPolicy(SHUTDOWN_INPUT_AT_END)); 1270c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller server.enqueue(new MockResponse() 1271c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller .addHeader("Content-Encoding: gzip") 1272e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody(gzip("b"))); 1273c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller 1274c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller // Seed the pool with a bad connection. 1275c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller assertContent("a", client.open(server.getUrl("/"))); 1276c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller 1277c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller // This connection will need to be recovered. When it is, transparent gzip should still work! 1278c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller assertContent("b", client.open(server.getUrl("/"))); 1279c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller 1280c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller assertEquals(0, server.takeRequest().getSequenceNumber()); 1281c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller assertEquals(0, server.takeRequest().getSequenceNumber()); // Connection is not pooled. 1282c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller } 1283c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller 1284c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller @Test public void endOfStreamResponseIsNotPooled() throws Exception { 1285c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller server.enqueue(new MockResponse() 1286c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller .setBody("{}") 1287c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller .clearHeaders() 1288c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller .setSocketPolicy(DISCONNECT_AT_END)); 1289c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller 1290c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller ConnectionPool pool = ConnectionPool.getDefault(); 1291c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller pool.evictAll(); 1292e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setConnectionPool(pool); 1293c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller 1294c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller HttpURLConnection connection = client.open(server.getUrl("/")); 1295c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller assertContent("{}", connection); 12966c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer assertEquals(0, client.client().getConnectionPool().getIdleConnectionCount()); 1297c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller } 1298c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller 129954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void earlyDisconnectDoesntHarmPoolingWithChunkedEncoding() throws Exception { 130054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson testEarlyDisconnectDoesntHarmPooling(TransferKind.CHUNKED); 130154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 130254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 130354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void earlyDisconnectDoesntHarmPoolingWithFixedLengthEncoding() throws Exception { 130454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson testEarlyDisconnectDoesntHarmPooling(TransferKind.FIXED_LENGTH); 130554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 130654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 130754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson private void testEarlyDisconnectDoesntHarmPooling(TransferKind transferKind) throws Exception { 130854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson MockResponse response1 = new MockResponse(); 130954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson transferKind.setBody(response1, "ABCDEFGHIJK", 1024); 131054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(response1); 131154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 131254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson MockResponse response2 = new MockResponse(); 131354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson transferKind.setBody(response2, "LMNOPQRSTUV", 1024); 131454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(response2); 131554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 13163c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller HttpURLConnection connection1 = client.open(server.getUrl("/")); 131754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson InputStream in1 = connection1.getInputStream(); 131854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals("ABCDE", readAscii(in1, 5)); 131987ed7244fb53ae2bac9f23c033bbd5f23ac269f8Jesse Wilson in1.close(); 13203c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection1.disconnect(); 132154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 132254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson HttpURLConnection connection2 = client.open(server.getUrl("/")); 132354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson InputStream in2 = connection2.getInputStream(); 132454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals("LMNOP", readAscii(in2, 5)); 132587ed7244fb53ae2bac9f23c033bbd5f23ac269f8Jesse Wilson in2.close(); 13263c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection2.disconnect(); 132754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 132854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals(0, server.takeRequest().getSequenceNumber()); 132954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals(1, server.takeRequest().getSequenceNumber()); // Connection is pooled! 133054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 133154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 13323c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Test public void streamDiscardingIsTimely() throws Exception { 13333c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller // This response takes at least a full second to serve: 10,000 bytes served 100 bytes at a time. 13343c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller server.enqueue(new MockResponse() 1335e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody(new Buffer().write(new byte[10000])) 13363c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller .throttleBody(100, 10, MILLISECONDS)); 13373c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller server.enqueue(new MockResponse().setBody("A")); 13383c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 13393c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller long startNanos = System.nanoTime(); 13403c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller URLConnection connection1 = client.open(server.getUrl("/")); 13413c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller InputStream in = connection1.getInputStream(); 13423c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller in.close(); 13433c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller long elapsedNanos = System.nanoTime() - startNanos; 13443c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller long elapsedMillis = NANOSECONDS.toMillis(elapsedNanos); 13453c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 13463c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller // If we're working correctly, this should be greater than 100ms, but less than double that. 13473c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller // Previously we had a bug where we would download the entire response body as long as no 13483c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller // individual read took longer than 100ms. 13493c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertTrue(String.format("Time to close: %sms", elapsedMillis), elapsedMillis < 500); 13503c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 13513c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller // Do another request to confirm that the discarded connection was not pooled. 13523c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertContent("A", client.open(server.getUrl("/"))); 13533c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 13543c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals(0, server.takeRequest().getSequenceNumber()); 13553c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals(0, server.takeRequest().getSequenceNumber()); // Connection is not pooled. 13563c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 13573c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 135854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void setChunkedStreamingMode() throws IOException, InterruptedException { 135954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse()); 136054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 13613c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller String body = "ABCDEFGHIJKLMNOPQ"; 13623c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/")); 13633c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection.setChunkedStreamingMode(0); // OkHttp does not honor specific chunk sizes. 13643c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection.setDoOutput(true); 13653c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller OutputStream outputStream = connection.getOutputStream(); 13663c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller outputStream.write(body.getBytes("US-ASCII")); 13673c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals(200, connection.getResponseCode()); 13686c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer connection.getInputStream().close(); 136954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 137054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson RecordedRequest request = server.takeRequest(); 1371e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(body, request.getBody().readUtf8()); 13723c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals(Arrays.asList(body.length()), request.getChunkSizes()); 137354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 137454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 137554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void authenticateWithFixedLengthStreaming() throws Exception { 137654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson testAuthenticateWithStreamingPost(StreamingMode.FIXED_LENGTH); 137754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 137854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 137954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void authenticateWithChunkedStreaming() throws Exception { 138054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson testAuthenticateWithStreamingPost(StreamingMode.CHUNKED); 138154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 138254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 138354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson private void testAuthenticateWithStreamingPost(StreamingMode streamingMode) throws Exception { 138454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson MockResponse pleaseAuthenticate = new MockResponse().setResponseCode(401) 138554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson .addHeader("WWW-Authenticate: Basic realm=\"protected area\"") 138654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson .setBody("Please authenticate."); 138754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(pleaseAuthenticate); 138854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 138954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson Authenticator.setDefault(new RecordingAuthenticator()); 13903c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/")); 139154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson connection.setDoOutput(true); 139254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson byte[] requestBody = { 'A', 'B', 'C', 'D' }; 139354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson if (streamingMode == StreamingMode.FIXED_LENGTH) { 139454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson connection.setFixedLengthStreamingMode(requestBody.length); 139554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } else if (streamingMode == StreamingMode.CHUNKED) { 139654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson connection.setChunkedStreamingMode(0); 139754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 139854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson OutputStream outputStream = connection.getOutputStream(); 139954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson outputStream.write(requestBody); 140054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson outputStream.close(); 140154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson try { 140254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson connection.getInputStream(); 140354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson fail(); 140454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } catch (HttpRetryException expected) { 140554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 140654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 140754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson // no authorization header for the request... 140854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson RecordedRequest request = server.takeRequest(); 1409e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertNull(request.getHeader("Authorization")); 1410e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("ABCD", request.getBody().readUtf8()); 1411e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 1412e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1413e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void postBodyRetransmittedAfterAuthorizationFail() throws Exception { 1414e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller postBodyRetransmittedAfterAuthorizationFail("abc"); 1415e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 1416e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1417e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void postBodyRetransmittedAfterAuthorizationFail_SPDY_3() throws Exception { 1418e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller enableProtocol(Protocol.SPDY_3); 1419e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller postBodyRetransmittedAfterAuthorizationFail("abc"); 1420e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 1421e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1422e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void postBodyRetransmittedAfterAuthorizationFail_HTTP_2() throws Exception { 1423e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller enableProtocol(Protocol.HTTP_2); 1424e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller postBodyRetransmittedAfterAuthorizationFail("abc"); 1425e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 1426e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1427e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller /** Don't explode when resending an empty post. https://github.com/square/okhttp/issues/1131 */ 1428e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void postEmptyBodyRetransmittedAfterAuthorizationFail() throws Exception { 1429e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller postBodyRetransmittedAfterAuthorizationFail(""); 1430e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 1431e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1432e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void postEmptyBodyRetransmittedAfterAuthorizationFail_SPDY_3() throws Exception { 1433e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller enableProtocol(Protocol.SPDY_3); 1434e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller postBodyRetransmittedAfterAuthorizationFail(""); 1435e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 1436e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1437e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void postEmptyBodyRetransmittedAfterAuthorizationFail_HTTP_2() throws Exception { 1438e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller enableProtocol(Protocol.HTTP_2); 1439e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller postBodyRetransmittedAfterAuthorizationFail(""); 1440e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 1441e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1442e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller private void postBodyRetransmittedAfterAuthorizationFail(String body) throws Exception { 1443e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse().setResponseCode(401)); 1444e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse()); 1445e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1446e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller String credential = Credentials.basic("jesse", "secret"); 1447e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setAuthenticator(new RecordingOkAuthenticator(credential)); 1448e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1449e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller connection = client.open(server.getUrl("/")); 1450e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller connection.setDoOutput(true); 1451e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller OutputStream outputStream = connection.getOutputStream(); 1452e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller outputStream.write(body.getBytes("UTF-8")); 1453e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller outputStream.close(); 1454e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(200, connection.getResponseCode()); 1455e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1456e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller RecordedRequest recordedRequest1 = server.takeRequest(); 1457e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("POST", recordedRequest1.getMethod()); 1458e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(body, recordedRequest1.getBody().readUtf8()); 1459e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertNull(recordedRequest1.getHeader("Authorization")); 1460e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1461e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller RecordedRequest recordedRequest2 = server.takeRequest(); 1462e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("POST", recordedRequest2.getMethod()); 1463e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(body, recordedRequest2.getBody().readUtf8()); 1464e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(credential, recordedRequest2.getHeader("Authorization")); 146554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 146654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 146754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void nonStandardAuthenticationScheme() throws Exception { 146854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson List<String> calls = authCallsForHeader("WWW-Authenticate: Foo"); 146954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals(Collections.<String>emptyList(), calls); 147054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 147154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 147254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void nonStandardAuthenticationSchemeWithRealm() throws Exception { 147354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson List<String> calls = authCallsForHeader("WWW-Authenticate: Foo realm=\"Bar\""); 1474166772be0e5cfdaea1a64b9f63e4c8dbfe48cba3Narayan Kamath assertEquals(0, calls.size()); 147554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 147654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 147754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson // Digest auth is currently unsupported. Test that digest requests should fail reasonably. 147854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson // http://code.google.com/p/android/issues/detail?id=11140 147954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void digestAuthentication() throws Exception { 148054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson List<String> calls = authCallsForHeader("WWW-Authenticate: Digest " 148154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson + "realm=\"testrealm@host.com\", qop=\"auth,auth-int\", " 148254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson + "nonce=\"dcd98b7102dd2f0e8b11d0f600bfb0c093\", " 148354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson + "opaque=\"5ccc069c403ebaf9f0171e9517f40e41\""); 1484166772be0e5cfdaea1a64b9f63e4c8dbfe48cba3Narayan Kamath assertEquals(0, calls.size()); 148554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 148654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 148754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void allAttributesSetInServerAuthenticationCallbacks() throws Exception { 148854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson List<String> calls = authCallsForHeader("WWW-Authenticate: Basic realm=\"Bar\""); 148954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals(1, calls.size()); 149054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson URL url = server.getUrl("/"); 149154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson String call = calls.get(0); 149254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertTrue(call, call.contains("host=" + url.getHost())); 149354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertTrue(call, call.contains("port=" + url.getPort())); 1494e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertTrue(call, call.contains("site=" + url.getHost())); 149554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertTrue(call, call.contains("url=" + url)); 149654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertTrue(call, call.contains("type=" + Authenticator.RequestorType.SERVER)); 149754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertTrue(call, call.contains("prompt=Bar")); 149854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertTrue(call, call.contains("protocol=http")); 149954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertTrue(call, call.toLowerCase().contains("scheme=basic")); // lowercase for the RI. 150054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 150154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 150254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void allAttributesSetInProxyAuthenticationCallbacks() throws Exception { 150354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson List<String> calls = authCallsForHeader("Proxy-Authenticate: Basic realm=\"Bar\""); 150454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals(1, calls.size()); 150554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson URL url = server.getUrl("/"); 150654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson String call = calls.get(0); 150754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertTrue(call, call.contains("host=" + url.getHost())); 150854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertTrue(call, call.contains("port=" + url.getPort())); 1509e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertTrue(call, call.contains("site=" + url.getHost())); 151054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertTrue(call, call.contains("url=http://android.com")); 151154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertTrue(call, call.contains("type=" + Authenticator.RequestorType.PROXY)); 151254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertTrue(call, call.contains("prompt=Bar")); 151354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertTrue(call, call.contains("protocol=http")); 151454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertTrue(call, call.toLowerCase().contains("scheme=basic")); // lowercase for the RI. 151554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 151654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 151754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson private List<String> authCallsForHeader(String authHeader) throws IOException { 151854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson boolean proxy = authHeader.startsWith("Proxy-"); 151954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson int responseCode = proxy ? 407 : 401; 152054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson RecordingAuthenticator authenticator = new RecordingAuthenticator(null); 152154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson Authenticator.setDefault(authenticator); 15226c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer MockResponse pleaseAuthenticate = new MockResponse() 15236c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer .setResponseCode(responseCode) 152454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson .addHeader(authHeader) 152554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson .setBody("Please authenticate."); 152654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(pleaseAuthenticate); 152754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 152854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson if (proxy) { 152971b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller client.client().setProxy(server.toProxyAddress()); 153054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson connection = client.open(new URL("http://android.com")); 153154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } else { 153254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson connection = client.open(server.getUrl("/")); 153354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 153454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals(responseCode, connection.getResponseCode()); 15356c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer connection.getErrorStream().close(); 153654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson return authenticator.calls; 153754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 153854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 153954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void setValidRequestMethod() throws Exception { 154054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertValidRequestMethod("GET"); 154154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertValidRequestMethod("DELETE"); 154254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertValidRequestMethod("HEAD"); 154354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertValidRequestMethod("OPTIONS"); 154454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertValidRequestMethod("POST"); 154554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertValidRequestMethod("PUT"); 154654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertValidRequestMethod("TRACE"); 15473c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertValidRequestMethod("PATCH"); 154854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 154954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 155054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson private void assertValidRequestMethod(String requestMethod) throws Exception { 15513c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/")); 155254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson connection.setRequestMethod(requestMethod); 155354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals(requestMethod, connection.getRequestMethod()); 155454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 155554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 155654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void setInvalidRequestMethodLowercase() throws Exception { 155754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertInvalidRequestMethod("get"); 155854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 155954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 156054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void setInvalidRequestMethodConnect() throws Exception { 156154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertInvalidRequestMethod("CONNECT"); 156254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 156354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 156454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson private void assertInvalidRequestMethod(String requestMethod) throws Exception { 15653c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/")); 156654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson try { 156754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson connection.setRequestMethod(requestMethod); 156854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson fail(); 156954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } catch (ProtocolException expected) { 157054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 157154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 157254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 15733c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Test public void shoutcast() throws Exception { 15743c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller server.enqueue(new MockResponse().setStatus("ICY 200 OK") 15753c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller // .addHeader("HTTP/1.0 200 OK") 15763c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller .addHeader("Accept-Ranges: none") 15773c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller .addHeader("Content-Type: audio/mpeg") 15783c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller .addHeader("icy-br:128") 15793c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller .addHeader("ice-audio-info: bitrate=128;samplerate=44100;channels=2") 15803c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller .addHeader("icy-br:128") 15813c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller .addHeader("icy-description:Rock") 15823c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller .addHeader("icy-genre:riders") 15833c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller .addHeader("icy-name:A2RRock") 15843c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller .addHeader("icy-pub:1") 15853c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller .addHeader("icy-url:http://www.A2Rradio.com") 15863c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller .addHeader("Server: Icecast 2.3.3-kh8") 15873c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller .addHeader("Cache-Control: no-cache") 15883c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller .addHeader("Pragma: no-cache") 15893c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller .addHeader("Expires: Mon, 26 Jul 1997 05:00:00 GMT") 15903c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller .addHeader("icy-metaint:16000") 15913c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller .setBody("mp3 data")); 15923c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/")); 15933c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals(200, connection.getResponseCode()); 15943c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals("OK", connection.getResponseMessage()); 15953c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertContent("mp3 data", connection); 15963c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 15973c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 159854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void cannotSetNegativeFixedLengthStreamingMode() throws Exception { 15993c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/")); 160054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson try { 160154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson connection.setFixedLengthStreamingMode(-2); 160254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson fail(); 160354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } catch (IllegalArgumentException expected) { 160454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 160554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 160654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 160754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void canSetNegativeChunkedStreamingMode() throws Exception { 16083c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/")); 160954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson connection.setChunkedStreamingMode(-2); 161054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 161154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 161254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void cannotSetFixedLengthStreamingModeAfterConnect() throws Exception { 161354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse().setBody("A")); 16143c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/")); 161554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals("A", readAscii(connection.getInputStream(), Integer.MAX_VALUE)); 161654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson try { 161754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson connection.setFixedLengthStreamingMode(1); 161854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson fail(); 161954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } catch (IllegalStateException expected) { 162054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 162154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 162254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 162354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void cannotSetChunkedStreamingModeAfterConnect() throws Exception { 162454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse().setBody("A")); 16253c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/")); 162654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals("A", readAscii(connection.getInputStream(), Integer.MAX_VALUE)); 162754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson try { 162854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson connection.setChunkedStreamingMode(1); 162954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson fail(); 163054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } catch (IllegalStateException expected) { 163154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 163254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 163354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 163454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void cannotSetFixedLengthStreamingModeAfterChunkedStreamingMode() throws Exception { 16353c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/")); 163654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson connection.setChunkedStreamingMode(1); 163754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson try { 163854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson connection.setFixedLengthStreamingMode(1); 163954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson fail(); 164054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } catch (IllegalStateException expected) { 164154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 164254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 164354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 164454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void cannotSetChunkedStreamingModeAfterFixedLengthStreamingMode() throws Exception { 16453c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/")); 164654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson connection.setFixedLengthStreamingMode(1); 164754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson try { 164854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson connection.setChunkedStreamingMode(1); 164954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson fail(); 165054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } catch (IllegalStateException expected) { 165154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 165254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 165354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 165454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void secureFixedLengthStreaming() throws Exception { 165554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson testSecureStreamingPost(StreamingMode.FIXED_LENGTH); 165654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 165754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 165854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void secureChunkedStreaming() throws Exception { 165954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson testSecureStreamingPost(StreamingMode.CHUNKED); 166054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 166154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 166254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson /** 166354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson * Users have reported problems using HTTPS with streaming request bodies. 166454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson * http://code.google.com/p/android/issues/detail?id=12860 166554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson */ 166654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson private void testSecureStreamingPost(StreamingMode streamingMode) throws Exception { 166771b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller server.useHttps(sslContext.getSocketFactory(), false); 166854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse().setBody("Success!")); 166954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 1670e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setSslSocketFactory(sslContext.getSocketFactory()); 1671e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setHostnameVerifier(new RecordingHostnameVerifier()); 16723c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/")); 167354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson connection.setDoOutput(true); 167454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson byte[] requestBody = { 'A', 'B', 'C', 'D' }; 167554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson if (streamingMode == StreamingMode.FIXED_LENGTH) { 167654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson connection.setFixedLengthStreamingMode(requestBody.length); 167754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } else if (streamingMode == StreamingMode.CHUNKED) { 167854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson connection.setChunkedStreamingMode(0); 167954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 168054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson OutputStream outputStream = connection.getOutputStream(); 168154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson outputStream.write(requestBody); 168254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson outputStream.close(); 168354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals("Success!", readAscii(connection.getInputStream(), Integer.MAX_VALUE)); 168454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 168554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson RecordedRequest request = server.takeRequest(); 168654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals("POST / HTTP/1.1", request.getRequestLine()); 168754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson if (streamingMode == StreamingMode.FIXED_LENGTH) { 168854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals(Collections.<Integer>emptyList(), request.getChunkSizes()); 168954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } else if (streamingMode == StreamingMode.CHUNKED) { 169054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals(Arrays.asList(4), request.getChunkSizes()); 169154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 1692e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("ABCD", request.getBody().readUtf8()); 169354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 169454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 169554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson enum StreamingMode { 169654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson FIXED_LENGTH, CHUNKED 169754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 169854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 169954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void authenticateWithPost() throws Exception { 170054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson MockResponse pleaseAuthenticate = new MockResponse().setResponseCode(401) 170154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson .addHeader("WWW-Authenticate: Basic realm=\"protected area\"") 170254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson .setBody("Please authenticate."); 170354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson // fail auth three times... 170454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(pleaseAuthenticate); 170554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(pleaseAuthenticate); 170654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(pleaseAuthenticate); 170754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson // ...then succeed the fourth time 170854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse().setBody("Successful auth!")); 170954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 171054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson Authenticator.setDefault(new RecordingAuthenticator()); 17113c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/")); 171254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson connection.setDoOutput(true); 171354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson byte[] requestBody = { 'A', 'B', 'C', 'D' }; 171454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson OutputStream outputStream = connection.getOutputStream(); 171554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson outputStream.write(requestBody); 171654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson outputStream.close(); 171754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals("Successful auth!", readAscii(connection.getInputStream(), Integer.MAX_VALUE)); 171854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 171954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson // no authorization header for the first request... 172054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson RecordedRequest request = server.takeRequest(); 1721e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertNull(request.getHeader("Authorization")); 172254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 172354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson // ...but the three requests that follow include an authorization header 172454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson for (int i = 0; i < 3; i++) { 172554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson request = server.takeRequest(); 172654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals("POST / HTTP/1.1", request.getRequestLine()); 1727e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("Basic " + RecordingAuthenticator.BASE_64_CREDENTIALS, 1728e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller request.getHeader("Authorization")); 1729e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("ABCD", request.getBody().readUtf8()); 173054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 173154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 173254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 173354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void authenticateWithGet() throws Exception { 173454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson MockResponse pleaseAuthenticate = new MockResponse().setResponseCode(401) 173554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson .addHeader("WWW-Authenticate: Basic realm=\"protected area\"") 173654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson .setBody("Please authenticate."); 173754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson // fail auth three times... 173854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(pleaseAuthenticate); 173954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(pleaseAuthenticate); 174054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(pleaseAuthenticate); 174154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson // ...then succeed the fourth time 174254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse().setBody("Successful auth!")); 174354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 174454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson Authenticator.setDefault(new RecordingAuthenticator()); 17453c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/")); 174654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals("Successful auth!", readAscii(connection.getInputStream(), Integer.MAX_VALUE)); 174754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 174854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson // no authorization header for the first request... 174954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson RecordedRequest request = server.takeRequest(); 1750e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertNull(request.getHeader("Authorization")); 175154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 175254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson // ...but the three requests that follow requests include an authorization header 175354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson for (int i = 0; i < 3; i++) { 175454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson request = server.takeRequest(); 175554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals("GET / HTTP/1.1", request.getRequestLine()); 1756e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("Basic " + RecordingAuthenticator.BASE_64_CREDENTIALS, 1757e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller request.getHeader("Authorization")); 175854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 175954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 176054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 1761f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller /** https://code.google.com/p/android/issues/detail?id=74026 */ 1762f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller @Test public void authenticateWithGetAndTransparentGzip() throws Exception { 1763f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller MockResponse pleaseAuthenticate = new MockResponse().setResponseCode(401) 1764f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller .addHeader("WWW-Authenticate: Basic realm=\"protected area\"") 1765f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller .setBody("Please authenticate."); 1766f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller // fail auth three times... 1767f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller server.enqueue(pleaseAuthenticate); 1768f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller server.enqueue(pleaseAuthenticate); 1769f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller server.enqueue(pleaseAuthenticate); 1770f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller // ...then succeed the fourth time 1771f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller MockResponse successfulResponse = new MockResponse() 1772f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller .addHeader("Content-Encoding", "gzip") 1773e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody(gzip("Successful auth!")); 1774f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller server.enqueue(successfulResponse); 1775f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller 1776f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller Authenticator.setDefault(new RecordingAuthenticator()); 1777f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller connection = client.open(server.getUrl("/")); 1778f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller assertEquals("Successful auth!", readAscii(connection.getInputStream(), Integer.MAX_VALUE)); 1779f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller 1780f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller // no authorization header for the first request... 1781f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller RecordedRequest request = server.takeRequest(); 1782e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertNull(request.getHeader("Authorization")); 1783f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller 1784f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller // ...but the three requests that follow requests include an authorization header 1785f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller for (int i = 0; i < 3; i++) { 1786f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller request = server.takeRequest(); 1787f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller assertEquals("GET / HTTP/1.1", request.getRequestLine()); 1788e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("Basic " + RecordingAuthenticator.BASE_64_CREDENTIALS, 1789e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller request.getHeader("Authorization")); 1790f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller } 1791f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller } 1792f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller 1793166772be0e5cfdaea1a64b9f63e4c8dbfe48cba3Narayan Kamath /** https://github.com/square/okhttp/issues/342 */ 1794166772be0e5cfdaea1a64b9f63e4c8dbfe48cba3Narayan Kamath @Test public void authenticateRealmUppercase() throws Exception { 1795166772be0e5cfdaea1a64b9f63e4c8dbfe48cba3Narayan Kamath server.enqueue(new MockResponse().setResponseCode(401) 1796166772be0e5cfdaea1a64b9f63e4c8dbfe48cba3Narayan Kamath .addHeader("wWw-aUtHeNtIcAtE: bAsIc rEaLm=\"pRoTeCtEd aReA\"") 1797166772be0e5cfdaea1a64b9f63e4c8dbfe48cba3Narayan Kamath .setBody("Please authenticate.")); 1798166772be0e5cfdaea1a64b9f63e4c8dbfe48cba3Narayan Kamath server.enqueue(new MockResponse().setBody("Successful auth!")); 1799166772be0e5cfdaea1a64b9f63e4c8dbfe48cba3Narayan Kamath 1800166772be0e5cfdaea1a64b9f63e4c8dbfe48cba3Narayan Kamath Authenticator.setDefault(new RecordingAuthenticator()); 18013c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/")); 1802166772be0e5cfdaea1a64b9f63e4c8dbfe48cba3Narayan Kamath assertEquals("Successful auth!", readAscii(connection.getInputStream(), Integer.MAX_VALUE)); 1803166772be0e5cfdaea1a64b9f63e4c8dbfe48cba3Narayan Kamath } 1804166772be0e5cfdaea1a64b9f63e4c8dbfe48cba3Narayan Kamath 180554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void redirectedWithChunkedEncoding() throws Exception { 180654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson testRedirected(TransferKind.CHUNKED, true); 180754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 180854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 180954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void redirectedWithContentLengthHeader() throws Exception { 181054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson testRedirected(TransferKind.FIXED_LENGTH, true); 181154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 181254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 181354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void redirectedWithNoLengthHeaders() throws Exception { 181454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson testRedirected(TransferKind.END_OF_STREAM, false); 181554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 181654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 181754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson private void testRedirected(TransferKind transferKind, boolean reuse) throws Exception { 181854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson MockResponse response = new MockResponse().setResponseCode(HttpURLConnection.HTTP_MOVED_TEMP) 181954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson .addHeader("Location: /foo"); 182054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson transferKind.setBody(response, "This page has moved!", 10); 182154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(response); 182254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse().setBody("This is the new location!")); 182354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 182454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson URLConnection connection = client.open(server.getUrl("/")); 182554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals("This is the new location!", 182654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson readAscii(connection.getInputStream(), Integer.MAX_VALUE)); 182754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 182854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson RecordedRequest first = server.takeRequest(); 182954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals("GET / HTTP/1.1", first.getRequestLine()); 183054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson RecordedRequest retry = server.takeRequest(); 183154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals("GET /foo HTTP/1.1", retry.getRequestLine()); 183254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson if (reuse) { 183354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals("Expected connection reuse", 1, retry.getSequenceNumber()); 183454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 183554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 183654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 183754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void redirectedOnHttps() throws IOException, InterruptedException { 183871b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller server.useHttps(sslContext.getSocketFactory(), false); 183954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_MOVED_TEMP) 184054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson .addHeader("Location: /foo") 184154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson .setBody("This page has moved!")); 184254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse().setBody("This is the new location!")); 184354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 1844e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setSslSocketFactory(sslContext.getSocketFactory()); 1845e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setHostnameVerifier(new RecordingHostnameVerifier()); 18463c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/")); 184754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals("This is the new location!", 184854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson readAscii(connection.getInputStream(), Integer.MAX_VALUE)); 184954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 185054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson RecordedRequest first = server.takeRequest(); 185154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals("GET / HTTP/1.1", first.getRequestLine()); 185254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson RecordedRequest retry = server.takeRequest(); 185354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals("GET /foo HTTP/1.1", retry.getRequestLine()); 185454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals("Expected connection reuse", 1, retry.getSequenceNumber()); 185554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 185654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 185754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void notRedirectedFromHttpsToHttp() throws IOException, InterruptedException { 185871b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller server.useHttps(sslContext.getSocketFactory(), false); 185954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_MOVED_TEMP) 186054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson .addHeader("Location: http://anyhost/foo") 186154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson .setBody("This page has moved!")); 186254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 1863e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setFollowSslRedirects(false); 1864e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setSslSocketFactory(sslContext.getSocketFactory()); 1865e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setHostnameVerifier(new RecordingHostnameVerifier()); 18663c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/")); 186754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals("This page has moved!", readAscii(connection.getInputStream(), Integer.MAX_VALUE)); 186854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 186954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 187054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void notRedirectedFromHttpToHttps() throws IOException, InterruptedException { 187154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_MOVED_TEMP) 187254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson .addHeader("Location: https://anyhost/foo") 187354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson .setBody("This page has moved!")); 187454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 1875e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setFollowSslRedirects(false); 18763c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/")); 187754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals("This page has moved!", readAscii(connection.getInputStream(), Integer.MAX_VALUE)); 187854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 187954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 18807407d6984ce69693097befc9b72609a8156463bbNarayan Kamath @Test public void redirectedFromHttpsToHttpFollowingProtocolRedirects() throws Exception { 18817407d6984ce69693097befc9b72609a8156463bbNarayan Kamath server2.enqueue(new MockResponse().setBody("This is insecure HTTP!")); 18827407d6984ce69693097befc9b72609a8156463bbNarayan Kamath 188371b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller server.useHttps(sslContext.getSocketFactory(), false); 18847407d6984ce69693097befc9b72609a8156463bbNarayan Kamath server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_MOVED_TEMP) 18857407d6984ce69693097befc9b72609a8156463bbNarayan Kamath .addHeader("Location: " + server2.getUrl("/")) 18867407d6984ce69693097befc9b72609a8156463bbNarayan Kamath .setBody("This page has moved!")); 18877407d6984ce69693097befc9b72609a8156463bbNarayan Kamath 1888e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setSslSocketFactory(sslContext.getSocketFactory()); 1889e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setHostnameVerifier(new RecordingHostnameVerifier()); 1890e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setFollowSslRedirects(true); 18917407d6984ce69693097befc9b72609a8156463bbNarayan Kamath HttpsURLConnection connection = (HttpsURLConnection) client.open(server.getUrl("/")); 18927407d6984ce69693097befc9b72609a8156463bbNarayan Kamath assertContent("This is insecure HTTP!", connection); 18937407d6984ce69693097befc9b72609a8156463bbNarayan Kamath assertNull(connection.getCipherSuite()); 18947407d6984ce69693097befc9b72609a8156463bbNarayan Kamath assertNull(connection.getLocalCertificates()); 18957407d6984ce69693097befc9b72609a8156463bbNarayan Kamath assertNull(connection.getServerCertificates()); 18967407d6984ce69693097befc9b72609a8156463bbNarayan Kamath assertNull(connection.getPeerPrincipal()); 18977407d6984ce69693097befc9b72609a8156463bbNarayan Kamath assertNull(connection.getLocalPrincipal()); 18987407d6984ce69693097befc9b72609a8156463bbNarayan Kamath } 18997407d6984ce69693097befc9b72609a8156463bbNarayan Kamath 19007407d6984ce69693097befc9b72609a8156463bbNarayan Kamath @Test public void redirectedFromHttpToHttpsFollowingProtocolRedirects() throws Exception { 190171b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller server2.useHttps(sslContext.getSocketFactory(), false); 19027407d6984ce69693097befc9b72609a8156463bbNarayan Kamath server2.enqueue(new MockResponse().setBody("This is secure HTTPS!")); 19037407d6984ce69693097befc9b72609a8156463bbNarayan Kamath 19047407d6984ce69693097befc9b72609a8156463bbNarayan Kamath server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_MOVED_TEMP) 19057407d6984ce69693097befc9b72609a8156463bbNarayan Kamath .addHeader("Location: " + server2.getUrl("/")) 19067407d6984ce69693097befc9b72609a8156463bbNarayan Kamath .setBody("This page has moved!")); 19077407d6984ce69693097befc9b72609a8156463bbNarayan Kamath 1908e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setSslSocketFactory(sslContext.getSocketFactory()); 1909e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setHostnameVerifier(new RecordingHostnameVerifier()); 1910e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setFollowSslRedirects(true); 19113c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/")); 19127407d6984ce69693097befc9b72609a8156463bbNarayan Kamath assertContent("This is secure HTTPS!", connection); 19137407d6984ce69693097befc9b72609a8156463bbNarayan Kamath assertFalse(connection instanceof HttpsURLConnection); 19147407d6984ce69693097befc9b72609a8156463bbNarayan Kamath } 19157407d6984ce69693097befc9b72609a8156463bbNarayan Kamath 191654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void redirectToAnotherOriginServer() throws Exception { 19177407d6984ce69693097befc9b72609a8156463bbNarayan Kamath redirectToAnotherOriginServer(false); 19187407d6984ce69693097befc9b72609a8156463bbNarayan Kamath } 19197407d6984ce69693097befc9b72609a8156463bbNarayan Kamath 19207407d6984ce69693097befc9b72609a8156463bbNarayan Kamath @Test public void redirectToAnotherOriginServerWithHttps() throws Exception { 19217407d6984ce69693097befc9b72609a8156463bbNarayan Kamath redirectToAnotherOriginServer(true); 19227407d6984ce69693097befc9b72609a8156463bbNarayan Kamath } 19237407d6984ce69693097befc9b72609a8156463bbNarayan Kamath 19247407d6984ce69693097befc9b72609a8156463bbNarayan Kamath private void redirectToAnotherOriginServer(boolean https) throws Exception { 19257407d6984ce69693097befc9b72609a8156463bbNarayan Kamath if (https) { 192671b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller server.useHttps(sslContext.getSocketFactory(), false); 192771b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller server2.useHttps(sslContext.getSocketFactory(), false); 192871b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller server2.setProtocolNegotiationEnabled(false); 1929e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setSslSocketFactory(sslContext.getSocketFactory()); 1930e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setHostnameVerifier(new RecordingHostnameVerifier()); 19317407d6984ce69693097befc9b72609a8156463bbNarayan Kamath } 19327407d6984ce69693097befc9b72609a8156463bbNarayan Kamath 193354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server2.enqueue(new MockResponse().setBody("This is the 2nd server!")); 19347407d6984ce69693097befc9b72609a8156463bbNarayan Kamath server2.enqueue(new MockResponse().setBody("This is the 2nd server, again!")); 193554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 193654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_MOVED_TEMP) 193754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson .addHeader("Location: " + server2.getUrl("/").toString()) 193854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson .setBody("This page has moved!")); 193954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse().setBody("This is the first server again!")); 194054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 19413c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/")); 19427407d6984ce69693097befc9b72609a8156463bbNarayan Kamath assertContent("This is the 2nd server!", connection); 194354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals(server2.getUrl("/"), connection.getURL()); 194454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 194554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson // make sure the first server was careful to recycle the connection 19467407d6984ce69693097befc9b72609a8156463bbNarayan Kamath assertContent("This is the first server again!", client.open(server.getUrl("/"))); 19477407d6984ce69693097befc9b72609a8156463bbNarayan Kamath assertContent("This is the 2nd server, again!", client.open(server2.getUrl("/"))); 19487407d6984ce69693097befc9b72609a8156463bbNarayan Kamath 194971b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller String server1Host = server.getHostName() + ":" + server.getPort(); 195071b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller String server2Host = server2.getHostName() + ":" + server2.getPort(); 1951e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(server1Host, server.takeRequest().getHeader("Host")); 1952e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(server2Host, server2.takeRequest().getHeader("Host")); 19537407d6984ce69693097befc9b72609a8156463bbNarayan Kamath assertEquals("Expected connection reuse", 1, server.takeRequest().getSequenceNumber()); 19547407d6984ce69693097befc9b72609a8156463bbNarayan Kamath assertEquals("Expected connection reuse", 1, server2.takeRequest().getSequenceNumber()); 19557407d6984ce69693097befc9b72609a8156463bbNarayan Kamath } 19567407d6984ce69693097befc9b72609a8156463bbNarayan Kamath 19577407d6984ce69693097befc9b72609a8156463bbNarayan Kamath @Test public void redirectWithProxySelector() throws Exception { 19587407d6984ce69693097befc9b72609a8156463bbNarayan Kamath final List<URI> proxySelectionRequests = new ArrayList<URI>(); 1959e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setProxySelector(new ProxySelector() { 19607407d6984ce69693097befc9b72609a8156463bbNarayan Kamath @Override public List<Proxy> select(URI uri) { 19617407d6984ce69693097befc9b72609a8156463bbNarayan Kamath proxySelectionRequests.add(uri); 196271b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller MockWebServer proxyServer = (uri.getPort() == server.getPort()) 196371b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller ? server 196471b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller : server2; 19657407d6984ce69693097befc9b72609a8156463bbNarayan Kamath return Arrays.asList(proxyServer.toProxyAddress()); 19667407d6984ce69693097befc9b72609a8156463bbNarayan Kamath } 1967e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 19687407d6984ce69693097befc9b72609a8156463bbNarayan Kamath @Override public void connectFailed(URI uri, SocketAddress address, IOException failure) { 19697407d6984ce69693097befc9b72609a8156463bbNarayan Kamath throw new AssertionError(); 19707407d6984ce69693097befc9b72609a8156463bbNarayan Kamath } 19717407d6984ce69693097befc9b72609a8156463bbNarayan Kamath }); 197254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 19737407d6984ce69693097befc9b72609a8156463bbNarayan Kamath server2.enqueue(new MockResponse().setBody("This is the 2nd server!")); 19747407d6984ce69693097befc9b72609a8156463bbNarayan Kamath 19757407d6984ce69693097befc9b72609a8156463bbNarayan Kamath server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_MOVED_TEMP) 19767407d6984ce69693097befc9b72609a8156463bbNarayan Kamath .addHeader("Location: " + server2.getUrl("/b").toString()) 19777407d6984ce69693097befc9b72609a8156463bbNarayan Kamath .setBody("This page has moved!")); 19787407d6984ce69693097befc9b72609a8156463bbNarayan Kamath 19797407d6984ce69693097befc9b72609a8156463bbNarayan Kamath assertContent("This is the 2nd server!", client.open(server.getUrl("/a"))); 19807407d6984ce69693097befc9b72609a8156463bbNarayan Kamath 19816c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer assertEquals(Arrays.asList(server.getUrl("/").toURI(), server2.getUrl("/").toURI()), 19827407d6984ce69693097befc9b72609a8156463bbNarayan Kamath proxySelectionRequests); 1983e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 198454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 1985e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void redirectWithAuthentication() throws Exception { 1986e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server2.enqueue(new MockResponse().setBody("Page 2")); 1987e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1988e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse().setResponseCode(401)); 1989e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse().setResponseCode(302) 1990e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Location: " + server2.getUrl("/b"))); 1991e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1992e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setAuthenticator( 1993e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller new RecordingOkAuthenticator(Credentials.basic("jesse", "secret"))); 1994e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertContent("Page 2", client.open(server.getUrl("/a"))); 1995e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 1996e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller RecordedRequest redirectRequest = server2.takeRequest(); 1997e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertNull(redirectRequest.getHeader("Authorization")); 1998e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("/b", redirectRequest.getPath()); 199954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 200054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 200154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void response300MultipleChoiceWithPost() throws Exception { 200254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson // Chrome doesn't follow the redirect, but Firefox and the RI both do 200378092f38ebd93018ead53a87b53118dc829cbb8aNeil Fuller testResponseRedirectedWithPost(HttpURLConnection.HTTP_MULT_CHOICE, TransferKind.END_OF_STREAM); 200454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 200554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 200654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void response301MovedPermanentlyWithPost() throws Exception { 200778092f38ebd93018ead53a87b53118dc829cbb8aNeil Fuller testResponseRedirectedWithPost(HttpURLConnection.HTTP_MOVED_PERM, TransferKind.END_OF_STREAM); 200854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 200954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 201054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void response302MovedTemporarilyWithPost() throws Exception { 201178092f38ebd93018ead53a87b53118dc829cbb8aNeil Fuller testResponseRedirectedWithPost(HttpURLConnection.HTTP_MOVED_TEMP, TransferKind.END_OF_STREAM); 201254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 201354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 201454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void response303SeeOtherWithPost() throws Exception { 201578092f38ebd93018ead53a87b53118dc829cbb8aNeil Fuller testResponseRedirectedWithPost(HttpURLConnection.HTTP_SEE_OTHER, TransferKind.END_OF_STREAM); 201654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 201754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 201878092f38ebd93018ead53a87b53118dc829cbb8aNeil Fuller @Test public void postRedirectToGetWithChunkedRequest() throws Exception { 201978092f38ebd93018ead53a87b53118dc829cbb8aNeil Fuller testResponseRedirectedWithPost(HttpURLConnection.HTTP_MOVED_TEMP, TransferKind.CHUNKED); 202078092f38ebd93018ead53a87b53118dc829cbb8aNeil Fuller } 202178092f38ebd93018ead53a87b53118dc829cbb8aNeil Fuller 202278092f38ebd93018ead53a87b53118dc829cbb8aNeil Fuller @Test public void postRedirectToGetWithStreamedRequest() throws Exception { 202378092f38ebd93018ead53a87b53118dc829cbb8aNeil Fuller testResponseRedirectedWithPost(HttpURLConnection.HTTP_MOVED_TEMP, TransferKind.FIXED_LENGTH); 202478092f38ebd93018ead53a87b53118dc829cbb8aNeil Fuller } 202578092f38ebd93018ead53a87b53118dc829cbb8aNeil Fuller 202678092f38ebd93018ead53a87b53118dc829cbb8aNeil Fuller private void testResponseRedirectedWithPost(int redirectCode, TransferKind transferKind) 202778092f38ebd93018ead53a87b53118dc829cbb8aNeil Fuller throws Exception { 202854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse().setResponseCode(redirectCode) 202954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson .addHeader("Location: /page2") 203054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson .setBody("This page has moved!")); 203154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse().setBody("Page 2")); 203254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 20333c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/page1")); 203454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson connection.setDoOutput(true); 203578092f38ebd93018ead53a87b53118dc829cbb8aNeil Fuller transferKind.setForRequest(connection, 4); 203654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson byte[] requestBody = { 'A', 'B', 'C', 'D' }; 203754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson OutputStream outputStream = connection.getOutputStream(); 203854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson outputStream.write(requestBody); 203954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson outputStream.close(); 204054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals("Page 2", readAscii(connection.getInputStream(), Integer.MAX_VALUE)); 204154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertTrue(connection.getDoOutput()); 204254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 204354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson RecordedRequest page1 = server.takeRequest(); 204454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals("POST /page1 HTTP/1.1", page1.getRequestLine()); 2045e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("ABCD", page1.getBody().readUtf8()); 204654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 204754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson RecordedRequest page2 = server.takeRequest(); 204854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals("GET /page2 HTTP/1.1", page2.getRequestLine()); 204954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 205054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 2051166772be0e5cfdaea1a64b9f63e4c8dbfe48cba3Narayan Kamath @Test public void redirectedPostStripsRequestBodyHeaders() throws Exception { 2052e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_MOVED_TEMP) 2053166772be0e5cfdaea1a64b9f63e4c8dbfe48cba3Narayan Kamath .addHeader("Location: /page2")); 2054166772be0e5cfdaea1a64b9f63e4c8dbfe48cba3Narayan Kamath server.enqueue(new MockResponse().setBody("Page 2")); 2055166772be0e5cfdaea1a64b9f63e4c8dbfe48cba3Narayan Kamath 20563c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/page1")); 2057166772be0e5cfdaea1a64b9f63e4c8dbfe48cba3Narayan Kamath connection.setDoOutput(true); 2058166772be0e5cfdaea1a64b9f63e4c8dbfe48cba3Narayan Kamath connection.addRequestProperty("Content-Length", "4"); 2059166772be0e5cfdaea1a64b9f63e4c8dbfe48cba3Narayan Kamath connection.addRequestProperty("Content-Type", "text/plain; charset=utf-8"); 2060166772be0e5cfdaea1a64b9f63e4c8dbfe48cba3Narayan Kamath connection.addRequestProperty("Transfer-Encoding", "identity"); 2061166772be0e5cfdaea1a64b9f63e4c8dbfe48cba3Narayan Kamath OutputStream outputStream = connection.getOutputStream(); 2062166772be0e5cfdaea1a64b9f63e4c8dbfe48cba3Narayan Kamath outputStream.write("ABCD".getBytes("UTF-8")); 2063166772be0e5cfdaea1a64b9f63e4c8dbfe48cba3Narayan Kamath outputStream.close(); 2064166772be0e5cfdaea1a64b9f63e4c8dbfe48cba3Narayan Kamath assertEquals("Page 2", readAscii(connection.getInputStream(), Integer.MAX_VALUE)); 2065166772be0e5cfdaea1a64b9f63e4c8dbfe48cba3Narayan Kamath 2066166772be0e5cfdaea1a64b9f63e4c8dbfe48cba3Narayan Kamath assertEquals("POST /page1 HTTP/1.1", server.takeRequest().getRequestLine()); 2067166772be0e5cfdaea1a64b9f63e4c8dbfe48cba3Narayan Kamath 2068166772be0e5cfdaea1a64b9f63e4c8dbfe48cba3Narayan Kamath RecordedRequest page2 = server.takeRequest(); 2069166772be0e5cfdaea1a64b9f63e4c8dbfe48cba3Narayan Kamath assertEquals("GET /page2 HTTP/1.1", page2.getRequestLine()); 2070e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertNull(page2.getHeader("Content-Length")); 2071e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertNull(page2.getHeader("Content-Type")); 2072e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertNull(page2.getHeader("Transfer-Encoding")); 2073166772be0e5cfdaea1a64b9f63e4c8dbfe48cba3Narayan Kamath } 2074166772be0e5cfdaea1a64b9f63e4c8dbfe48cba3Narayan Kamath 207554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void response305UseProxy() throws Exception { 207654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_USE_PROXY) 207754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson .addHeader("Location: " + server.getUrl("/")) 207854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson .setBody("This page has moved!")); 207954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse().setBody("Proxy Response")); 208054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 20813c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/foo")); 208254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson // Fails on the RI, which gets "Proxy Response" 208354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals("This page has moved!", readAscii(connection.getInputStream(), Integer.MAX_VALUE)); 208454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 208554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson RecordedRequest page1 = server.takeRequest(); 208654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals("GET /foo HTTP/1.1", page1.getRequestLine()); 208754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals(1, server.getRequestCount()); 208854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 208954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 2090faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath @Test public void response307WithGet() throws Exception { 2091e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller testRedirect(true, "GET"); 2092faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath } 2093faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath 2094faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath @Test public void response307WithHead() throws Exception { 2095e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller testRedirect(true, "HEAD"); 2096faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath } 2097faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath 2098faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath @Test public void response307WithOptions() throws Exception { 2099e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller testRedirect(true, "OPTIONS"); 2100faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath } 2101faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath 2102faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath @Test public void response307WithPost() throws Exception { 2103e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller testRedirect(true, "POST"); 2104e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 2105e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 2106e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void response308WithGet() throws Exception { 2107e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller testRedirect(false, "GET"); 2108e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 2109e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 2110e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void response308WithHead() throws Exception { 2111e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller testRedirect(false, "HEAD"); 2112e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 2113e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 2114e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void response308WithOptions() throws Exception { 2115e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller testRedirect(false, "OPTIONS"); 2116e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 2117e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 2118e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void response308WithPost() throws Exception { 2119e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller testRedirect(false, "POST"); 2120faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath } 2121faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath 2122e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller private void testRedirect(boolean temporary, String method) throws Exception { 2123faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath MockResponse response1 = new MockResponse() 2124e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setResponseCode(temporary ? HTTP_TEMP_REDIRECT : HTTP_PERM_REDIRECT) 2125faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath .addHeader("Location: /page2"); 2126faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath if (!method.equals("HEAD")) { 2127faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath response1.setBody("This page has moved!"); 2128faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath } 2129faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath server.enqueue(response1); 2130faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath server.enqueue(new MockResponse().setBody("Page 2")); 2131faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath 21323c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/page1")); 2133faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath connection.setRequestMethod(method); 2134faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath byte[] requestBody = { 'A', 'B', 'C', 'D' }; 2135faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath if (method.equals("POST")) { 2136faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath connection.setDoOutput(true); 2137faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath OutputStream outputStream = connection.getOutputStream(); 2138faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath outputStream.write(requestBody); 2139faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath outputStream.close(); 2140faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath } 2141faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath 2142faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath String response = readAscii(connection.getInputStream(), Integer.MAX_VALUE); 2143faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath 2144faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath RecordedRequest page1 = server.takeRequest(); 2145faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath assertEquals(method + " /page1 HTTP/1.1", page1.getRequestLine()); 2146faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath 2147faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath if (method.equals("GET")) { 2148d7254e38efa2f20db6cac1a5cb5ac4548edc3d46Neil Fuller assertEquals("Page 2", response); 2149e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } else if (method.equals("HEAD")) { 2150d7254e38efa2f20db6cac1a5cb5ac4548edc3d46Neil Fuller assertEquals("", response); 2151faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath } else { 2152faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath // Methods other than GET/HEAD shouldn't follow the redirect 2153faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath if (method.equals("POST")) { 2154faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath assertTrue(connection.getDoOutput()); 2155e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("ABCD", page1.getBody().readUtf8()); 2156faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath } 2157faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath assertEquals(1, server.getRequestCount()); 2158faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath assertEquals("This page has moved!", response); 2159faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath return; 2160faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath } 2161faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath 2162faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath // GET/HEAD requests should have followed the redirect with the same method 2163faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath assertFalse(connection.getDoOutput()); 2164faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath assertEquals(2, server.getRequestCount()); 2165faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath RecordedRequest page2 = server.takeRequest(); 2166faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath assertEquals(method + " /page2 HTTP/1.1", page2.getRequestLine()); 2167faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath } 2168faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath 216954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void follow20Redirects() throws Exception { 217054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson for (int i = 0; i < 20; i++) { 217154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_MOVED_TEMP) 217254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson .addHeader("Location: /" + (i + 1)) 217354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson .setBody("Redirecting to /" + (i + 1))); 217454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 217554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse().setBody("Success!")); 217654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 21773c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/0")); 217854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertContent("Success!", connection); 217954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals(server.getUrl("/20"), connection.getURL()); 218054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 218154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 218254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void doesNotFollow21Redirects() throws Exception { 218354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson for (int i = 0; i < 21; i++) { 218454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_MOVED_TEMP) 218554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson .addHeader("Location: /" + (i + 1)) 218654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson .setBody("Redirecting to /" + (i + 1))); 218754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 218854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 21893c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/0")); 219054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson try { 219154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson connection.getInputStream(); 219254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson fail(); 219354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } catch (ProtocolException expected) { 219454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals(HttpURLConnection.HTTP_MOVED_TEMP, connection.getResponseCode()); 2195e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("Too many follow-up requests: 21", expected.getMessage()); 219654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertContent("Redirecting to /21", connection); 219754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals(server.getUrl("/20"), connection.getURL()); 219854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 219954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 220054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 220154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void httpsWithCustomTrustManager() throws Exception { 220254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson RecordingHostnameVerifier hostnameVerifier = new RecordingHostnameVerifier(); 22036c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer RecordingTrustManager trustManager = new RecordingTrustManager(sslContext); 220454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson SSLContext sc = SSLContext.getInstance("TLS"); 22056c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer sc.init(null, new TrustManager[] {trustManager}, new SecureRandom()); 220654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 2207e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setHostnameVerifier(hostnameVerifier); 2208e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setSslSocketFactory(sc.getSocketFactory()); 220971b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller server.useHttps(sslContext.getSocketFactory(), false); 221054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse().setBody("ABC")); 221154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse().setBody("DEF")); 221254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse().setBody("GHI")); 221354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 221454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson URL url = server.getUrl("/"); 221554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertContent("ABC", client.open(url)); 221654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertContent("DEF", client.open(url)); 221754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertContent("GHI", client.open(url)); 221854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 22196c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer assertEquals(Arrays.asList("verify " + server.getHostName()), hostnameVerifier.calls); 222071b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller assertEquals(Arrays.asList("checkServerTrusted [CN=" + server.getHostName() + " 1]"), 2221e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller trustManager.calls); 222254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 222354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 222454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void readTimeouts() throws IOException { 222554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson // This relies on the fact that MockWebServer doesn't close the 222654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson // connection after a response has been sent. This causes the client to 222754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson // try to read more bytes than are sent, which results in a timeout. 222854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson MockResponse timeout = 222954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson new MockResponse().setBody("ABC").clearHeaders().addHeader("Content-Length: 4"); 223054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(timeout); 223154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse().setBody("unused")); // to keep the server alive 223254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 22333c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller URLConnection connection = client.open(server.getUrl("/")); 22343c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection.setReadTimeout(1000); 22353c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller InputStream in = connection.getInputStream(); 223654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals('A', in.read()); 223754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals('B', in.read()); 223854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals('C', in.read()); 223954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson try { 224054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson in.read(); // if Content-Length was accurate, this would return -1 immediately 224154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson fail(); 2242b5f9076b16fcc41c3dad31aecfdcfd962a7a1f75Neil Fuller } catch (SocketTimeoutException expected) { 2243e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 22446c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer in.close(); 2245e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 2246e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 2247e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller /** Confirm that an unacknowledged write times out. */ 2248e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void writeTimeouts() throws IOException { 2249d22dae2ff3c14d458829d7082651f3e6baa9b65dNeil Fuller MockWebServer server = new MockWebServer(); 2250e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // Sockets on some platforms can have large buffers that mean writes do not block when 2251e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // required. These socket factories explicitly set the buffer sizes on sockets created. 2252e0d02d710cd1bbcc1a9065ede7f6801f72abe5b7Neil Fuller final int SOCKET_BUFFER_SIZE = 4 * 1024; 225371b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller server.setServerSocketFactory( 2254e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller new DelegatingServerSocketFactory(ServerSocketFactory.getDefault()) { 2255e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Override 225671b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller protected ServerSocket configureServerSocket(ServerSocket serverSocket) 225771b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller throws IOException { 2258e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller serverSocket.setReceiveBufferSize(SOCKET_BUFFER_SIZE); 225971b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller return serverSocket; 2260e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 2261e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller }); 2262e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setSocketFactory(new DelegatingSocketFactory(SocketFactory.getDefault()) { 2263e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Override 226471b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller protected Socket configureSocket(Socket socket) throws IOException { 2265e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller socket.setReceiveBufferSize(SOCKET_BUFFER_SIZE); 2266e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller socket.setSendBufferSize(SOCKET_BUFFER_SIZE); 226771b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller return socket; 2268e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 2269e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller }); 2270e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 2271d22dae2ff3c14d458829d7082651f3e6baa9b65dNeil Fuller server.start(); 2272e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 2273e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .throttleBody(1, 1, TimeUnit.SECONDS)); // Prevent the server from reading! 2274e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 2275e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setWriteTimeout(500, TimeUnit.MILLISECONDS); 2276e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller connection = client.open(server.getUrl("/")); 2277e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller connection.setDoOutput(true); 2278e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller connection.setChunkedStreamingMode(0); 2279e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller OutputStream out = connection.getOutputStream(); 2280e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller try { 2281e0d02d710cd1bbcc1a9065ede7f6801f72abe5b7Neil Fuller byte[] data = new byte[2 * 1024 * 1024]; // 2 MiB. 2282e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller out.write(data); 2283e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller fail(); 2284b5f9076b16fcc41c3dad31aecfdcfd962a7a1f75Neil Fuller } catch (SocketTimeoutException expected) { 228554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 228654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 228754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 228854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void setChunkedEncodingAsRequestProperty() throws IOException, InterruptedException { 228954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse()); 229054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 22913c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/")); 22923c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection.setRequestProperty("Transfer-encoding", "chunked"); 22933c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection.setDoOutput(true); 22943c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection.getOutputStream().write("ABC".getBytes("UTF-8")); 22953c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals(200, connection.getResponseCode()); 229654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 229754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson RecordedRequest request = server.takeRequest(); 2298e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("ABC", request.getBody().readUtf8()); 229954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 230054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 230154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void connectionCloseInRequest() throws IOException, InterruptedException { 230254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse()); // server doesn't honor the connection: close header! 230354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse()); 230454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 230554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson HttpURLConnection a = client.open(server.getUrl("/")); 230654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson a.setRequestProperty("Connection", "close"); 230754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals(200, a.getResponseCode()); 230854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 230954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson HttpURLConnection b = client.open(server.getUrl("/")); 231054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals(200, b.getResponseCode()); 231154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 231254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals(0, server.takeRequest().getSequenceNumber()); 231354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals("When connection: close is used, each request should get its own connection", 0, 231454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.takeRequest().getSequenceNumber()); 231554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 231654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 231754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void connectionCloseInResponse() throws IOException, InterruptedException { 231854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse().addHeader("Connection: close")); 231954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse()); 232054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 232154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson HttpURLConnection a = client.open(server.getUrl("/")); 232254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals(200, a.getResponseCode()); 232354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 232454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson HttpURLConnection b = client.open(server.getUrl("/")); 232554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals(200, b.getResponseCode()); 232654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 232754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals(0, server.takeRequest().getSequenceNumber()); 232854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals("When connection: close is used, each request should get its own connection", 0, 232954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.takeRequest().getSequenceNumber()); 233054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 233154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 233254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void connectionCloseWithRedirect() throws IOException, InterruptedException { 233354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson MockResponse response = new MockResponse().setResponseCode(HttpURLConnection.HTTP_MOVED_TEMP) 233454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson .addHeader("Location: /foo") 233554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson .addHeader("Connection: close"); 233654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(response); 233754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse().setBody("This is the new location!")); 233854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 233954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson URLConnection connection = client.open(server.getUrl("/")); 234054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals("This is the new location!", 234154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson readAscii(connection.getInputStream(), Integer.MAX_VALUE)); 234254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 234354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals(0, server.takeRequest().getSequenceNumber()); 234454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals("When connection: close is used, each request should get its own connection", 0, 234554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.takeRequest().getSequenceNumber()); 234654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 234754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 234854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson /** 234954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson * Retry redirects if the socket is closed. 235054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson * https://code.google.com/p/android/issues/detail?id=41576 235154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson */ 235254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void sameConnectionRedirectAndReuse() throws Exception { 235354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_MOVED_TEMP) 235454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson .setSocketPolicy(SHUTDOWN_INPUT_AT_END) 235554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson .addHeader("Location: /foo")); 235654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse().setBody("This is the new page!")); 235754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 235854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertContent("This is the new page!", client.open(server.getUrl("/"))); 235954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 236054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals(0, server.takeRequest().getSequenceNumber()); 236154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals(0, server.takeRequest().getSequenceNumber()); 236254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 236354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 236454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void responseCodeDisagreesWithHeaders() throws IOException, InterruptedException { 236554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_NO_CONTENT) 236654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson .setBody("This body is not allowed!")); 236754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 236854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson URLConnection connection = client.open(server.getUrl("/")); 236954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals("This body is not allowed!", 237054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson readAscii(connection.getInputStream(), Integer.MAX_VALUE)); 237154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 237254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 237354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void singleByteReadIsSigned() throws IOException { 2374e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse().setBody(new Buffer().writeByte(-2).writeByte(-1))); 237554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 23763c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/")); 237754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson InputStream in = connection.getInputStream(); 237854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals(254, in.read()); 237954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals(255, in.read()); 238054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals(-1, in.read()); 238154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 238254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 238354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void flushAfterStreamTransmittedWithChunkedEncoding() throws IOException { 238454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson testFlushAfterStreamTransmitted(TransferKind.CHUNKED); 238554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 238654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 238754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void flushAfterStreamTransmittedWithFixedLength() throws IOException { 238854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson testFlushAfterStreamTransmitted(TransferKind.FIXED_LENGTH); 238954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 239054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 239154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void flushAfterStreamTransmittedWithNoLengthHeaders() throws IOException { 239254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson testFlushAfterStreamTransmitted(TransferKind.END_OF_STREAM); 239354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 239454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 239554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson /** 239654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson * We explicitly permit apps to close the upload stream even after it has 239754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson * been transmitted. We also permit flush so that buffered streams can 239854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson * do a no-op flush when they are closed. http://b/3038470 239954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson */ 240054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson private void testFlushAfterStreamTransmitted(TransferKind transferKind) throws IOException { 240154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse().setBody("abc")); 240254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 24033c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/")); 240454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson connection.setDoOutput(true); 240554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson byte[] upload = "def".getBytes("UTF-8"); 240654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 240754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson if (transferKind == TransferKind.CHUNKED) { 240854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson connection.setChunkedStreamingMode(0); 240954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } else if (transferKind == TransferKind.FIXED_LENGTH) { 241054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson connection.setFixedLengthStreamingMode(upload.length); 241154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 241254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 241354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson OutputStream out = connection.getOutputStream(); 241454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson out.write(upload); 241554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals("abc", readAscii(connection.getInputStream(), Integer.MAX_VALUE)); 241654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 24173c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller out.flush(); // Dubious but permitted. 241854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson try { 241954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson out.write("ghi".getBytes("UTF-8")); 242054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson fail(); 242154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } catch (IOException expected) { 242254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 242354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 242454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 242554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void getHeadersThrows() throws IOException { 2426e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse().setSocketPolicy(DISCONNECT_AT_START)); 242754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 24283c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/")); 242954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson try { 243054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson connection.getInputStream(); 243154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson fail(); 243254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } catch (IOException expected) { 243354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 243454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 243554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson try { 243654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson connection.getInputStream(); 243754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson fail(); 243854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } catch (IOException expected) { 243954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 244054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 244154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 244254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void dnsFailureThrowsIOException() throws IOException { 24433c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(new URL("http://host.unlikelytld")); 244454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson try { 244554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson connection.connect(); 244654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson fail(); 244754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } catch (IOException expected) { 244854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 244954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 245054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 245154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void malformedUrlThrowsUnknownHostException() throws IOException { 2452ca342d6c3c54ae2417d4e61c925ba6f63b31a571jwilson connection = client.open(new URL("http://./foo.html")); 245354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson try { 245454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson connection.connect(); 245554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson fail(); 245654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } catch (UnknownHostException expected) { 245754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 245854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 245954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 246054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void getKeepAlive() throws Exception { 246154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse().setBody("ABC")); 246254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 246354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson // The request should work once and then fail 246471b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller HttpURLConnection connection1 = client.open(server.getUrl("/")); 246554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson connection1.setReadTimeout(100); 246654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson InputStream input = connection1.getInputStream(); 246754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals("ABC", readAscii(input, Integer.MAX_VALUE)); 246871b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller server.shutdown(); 246954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson try { 247054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson HttpURLConnection connection2 = client.open(server.getUrl("")); 247154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson connection2.setReadTimeout(100); 247254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson connection2.getInputStream(); 247354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson fail(); 247454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } catch (ConnectException expected) { 247554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 247654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 247754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 247854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson /** http://code.google.com/p/android/issues/detail?id=14562 */ 247954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void readAfterLastByte() throws Exception { 248054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse().setBody("ABC") 248154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson .clearHeaders() 248254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson .addHeader("Connection: close") 248354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson .setSocketPolicy(SocketPolicy.DISCONNECT_AT_END)); 248454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 24853c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/")); 248654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson InputStream in = connection.getInputStream(); 248754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals("ABC", readAscii(in, 3)); 248854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals(-1, in.read()); 248954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals(-1, in.read()); // throws IOException in Gingerbread 249054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 249154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 249254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void getContent() throws Exception { 249354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse().addHeader("Content-Type: text/plain").setBody("A")); 24943c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/")); 249554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson InputStream in = (InputStream) connection.getContent(); 249654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals("A", readAscii(in, Integer.MAX_VALUE)); 249754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 249854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 249954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void getContentOfType() throws Exception { 250054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse().addHeader("Content-Type: text/plain").setBody("A")); 25013c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/")); 250254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson try { 250354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson connection.getContent(null); 250454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson fail(); 250554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } catch (NullPointerException expected) { 250654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 250754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson try { 250854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson connection.getContent(new Class[] { null }); 250954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson fail(); 251054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } catch (NullPointerException expected) { 251154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 251271b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller assertNull(connection.getContent(new Class[] { getClass() })); 25136c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer connection.getInputStream().close(); 251454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 251554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 251654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void getOutputStreamOnGetFails() throws Exception { 251754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse()); 25183c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/")); 251954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson try { 252054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson connection.getOutputStream(); 252154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson fail(); 252254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } catch (ProtocolException expected) { 252354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 25246c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer connection.getInputStream().close(); 252554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 252654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 252754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void getOutputAfterGetInputStreamFails() throws Exception { 252854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse()); 25293c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/")); 253054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson connection.setDoOutput(true); 253154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson try { 253254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson connection.getInputStream(); 253354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson connection.getOutputStream(); 253454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson fail(); 253554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } catch (ProtocolException expected) { 253654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 253754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 253854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 253954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void setDoOutputOrDoInputAfterConnectFails() throws Exception { 254054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse()); 25413c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/")); 254254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson connection.connect(); 254354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson try { 254454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson connection.setDoOutput(true); 254554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson fail(); 254654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } catch (IllegalStateException expected) { 254754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 254854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson try { 254954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson connection.setDoInput(true); 255054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson fail(); 255154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } catch (IllegalStateException expected) { 255254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 25536c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer connection.getInputStream().close(); 255454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 255554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 255654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void clientSendsContentLength() throws Exception { 255754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse().setBody("A")); 25583c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/")); 255954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson connection.setDoOutput(true); 256054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson OutputStream out = connection.getOutputStream(); 256154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson out.write(new byte[] { 'A', 'B', 'C' }); 256254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson out.close(); 256354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals("A", readAscii(connection.getInputStream(), Integer.MAX_VALUE)); 256454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson RecordedRequest request = server.takeRequest(); 2565e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("3", request.getHeader("Content-Length")); 25666c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer connection.getInputStream().close(); 256754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 256854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 256954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void getContentLengthConnects() throws Exception { 257054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse().setBody("ABC")); 25713c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/")); 257254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals(3, connection.getContentLength()); 25736c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer connection.getInputStream().close(); 257454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 257554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 257654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void getContentTypeConnects() throws Exception { 257754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse().addHeader("Content-Type: text/plain").setBody("ABC")); 25783c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/")); 257954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals("text/plain", connection.getContentType()); 25806c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer connection.getInputStream().close(); 258154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 258254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 258354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void getContentEncodingConnects() throws Exception { 258454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse().addHeader("Content-Encoding: identity").setBody("ABC")); 25853c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/")); 258654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals("identity", connection.getContentEncoding()); 25876c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer connection.getInputStream().close(); 258854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 258954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 259054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson // http://b/4361656 259154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void urlContainsQueryButNoPath() throws Exception { 259254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(new MockResponse().setBody("A")); 2593e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 259471b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller URL url = new URL("http", server.getHostName(), server.getPort(), "?query"); 259554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals("A", readAscii(client.open(url).getInputStream(), Integer.MAX_VALUE)); 259654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson RecordedRequest request = server.takeRequest(); 259754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals("GET /?query HTTP/1.1", request.getRequestLine()); 259854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 259954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 2600e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void doOutputForMethodThatDoesntSupportOutput() throws Exception { 2601e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller connection = client.open(server.getUrl("/")); 2602e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller connection.setRequestMethod("HEAD"); 2603e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller connection.setDoOutput(true); 2604e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller try { 2605e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller connection.connect(); 2606e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller fail(); 2607e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } catch (IOException expected) { 2608e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 2609e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 2610e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 261154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson // http://code.google.com/p/android/issues/detail?id=20442 261254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void inputStreamAvailableWithChunkedEncoding() throws Exception { 261354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson testInputStreamAvailable(TransferKind.CHUNKED); 261454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 261554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 261654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void inputStreamAvailableWithContentLengthHeader() throws Exception { 261754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson testInputStreamAvailable(TransferKind.FIXED_LENGTH); 261854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 261954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 262054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test public void inputStreamAvailableWithNoLengthHeaders() throws Exception { 262154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson testInputStreamAvailable(TransferKind.END_OF_STREAM); 262254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 262354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 262454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson private void testInputStreamAvailable(TransferKind transferKind) throws IOException { 262554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson String body = "ABCDEFGH"; 262654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson MockResponse response = new MockResponse(); 262754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson transferKind.setBody(response, body, 4); 262854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson server.enqueue(response); 26293c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/")); 263054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson InputStream in = connection.getInputStream(); 263154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson for (int i = 0; i < body.length(); i++) { 263254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertTrue(in.available() >= 0); 263354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals(body.charAt(i), in.read()); 263454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 263554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals(0, in.available()); 263654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals(-1, in.read()); 263754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 263854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 2639faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath @Test public void postFailsWithBufferedRequestForSmallRequest() throws Exception { 2640faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath reusedConnectionFailsWithPost(TransferKind.END_OF_STREAM, 1024); 2641faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath } 2642faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath 2643fb0eb65be9f50e75fa37c250e97914252c587cafjwilson @Test public void postFailsWithBufferedRequestForLargeRequest() throws Exception { 2644faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath reusedConnectionFailsWithPost(TransferKind.END_OF_STREAM, 16384); 2645faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath } 2646faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath 2647faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath @Test public void postFailsWithChunkedRequestForSmallRequest() throws Exception { 2648faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath reusedConnectionFailsWithPost(TransferKind.CHUNKED, 1024); 2649faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath } 2650faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath 2651fb0eb65be9f50e75fa37c250e97914252c587cafjwilson @Test public void postFailsWithChunkedRequestForLargeRequest() throws Exception { 2652faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath reusedConnectionFailsWithPost(TransferKind.CHUNKED, 16384); 2653faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath } 2654faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath 2655faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath @Test public void postFailsWithFixedLengthRequestForSmallRequest() throws Exception { 2656faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath reusedConnectionFailsWithPost(TransferKind.FIXED_LENGTH, 1024); 2657faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath } 2658faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath 2659fb0eb65be9f50e75fa37c250e97914252c587cafjwilson @Test public void postFailsWithFixedLengthRequestForLargeRequest() throws Exception { 2660faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath reusedConnectionFailsWithPost(TransferKind.FIXED_LENGTH, 16384); 2661faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath } 2662faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath 2663faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath private void reusedConnectionFailsWithPost(TransferKind transferKind, int requestSize) 2664faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath throws Exception { 2665e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse().setBody("A").setSocketPolicy(DISCONNECT_AT_END)); 2666faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath server.enqueue(new MockResponse().setBody("B")); 26673c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller server.enqueue(new MockResponse().setBody("C")); 2668faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath 2669faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath assertContent("A", client.open(server.getUrl("/a"))); 2670faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath 2671faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath // If the request body is larger than OkHttp's replay buffer, the failure may still occur. 2672faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath byte[] requestBody = new byte[requestSize]; 2673faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath new Random(0).nextBytes(requestBody); 2674faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath 2675a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller for (int j = 0; j < 2; j++) { 2676a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller try { 2677a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller connection = client.open(server.getUrl("/b")); 2678a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller connection.setRequestMethod("POST"); 2679a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller transferKind.setForRequest(connection, requestBody.length); 2680a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller for (int i = 0; i < requestBody.length; i += 1024) { 2681a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller connection.getOutputStream().write(requestBody, i, 1024); 2682a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller } 2683a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller connection.getOutputStream().close(); 2684a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller assertContent("B", connection); 2685a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller break; 2686a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller } catch (IOException socketException) { 2687a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller // If there's a socket exception, this must have a streamed request body. 2688a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller assertEquals(0, j); 2689a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller assertTrue(transferKind == TransferKind.CHUNKED 2690a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller || transferKind == TransferKind.FIXED_LENGTH); 2691a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller } 2692faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath } 2693faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath 2694faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath RecordedRequest requestA = server.takeRequest(); 2695faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath assertEquals("/a", requestA.getPath()); 2696faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath RecordedRequest requestB = server.takeRequest(); 2697faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath assertEquals("/b", requestB.getPath()); 2698e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(Arrays.toString(requestBody), Arrays.toString(requestB.getBody().readByteArray())); 2699e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 2700e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 2701e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void postBodyRetransmittedOnFailureRecovery() throws Exception { 2702e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse().setBody("abc")); 2703e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse().setSocketPolicy(SocketPolicy.DISCONNECT_AFTER_REQUEST)); 2704e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse().setBody("def")); 2705e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 2706e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // Seed the connection pool so we have something that can fail. 2707e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertContent("abc", client.open(server.getUrl("/"))); 2708e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 2709e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller HttpURLConnection post = client.open(server.getUrl("/")); 2710e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller post.setDoOutput(true); 2711e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller post.getOutputStream().write("body!".getBytes(Util.UTF_8)); 2712e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertContent("def", post); 2713e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 2714e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller RecordedRequest get = server.takeRequest(); 2715e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(0, get.getSequenceNumber()); 2716e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 2717e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller RecordedRequest post1 = server.takeRequest(); 2718e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("body!", post1.getBody().readUtf8()); 2719e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(1, post1.getSequenceNumber()); 2720e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 2721e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller RecordedRequest post2 = server.takeRequest(); 2722e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("body!", post2.getBody().readUtf8()); 2723e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(0, post2.getSequenceNumber()); 2724faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath } 2725faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath 2726faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath @Test public void fullyBufferedPostIsTooShort() throws Exception { 2727faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath server.enqueue(new MockResponse().setBody("A")); 2728faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath 27293c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/b")); 2730faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath connection.setRequestProperty("Content-Length", "4"); 2731faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath connection.setRequestMethod("POST"); 2732faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath OutputStream out = connection.getOutputStream(); 2733faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath out.write('a'); 2734faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath out.write('b'); 2735faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath out.write('c'); 2736faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath try { 2737faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath out.close(); 2738faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath fail(); 2739faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath } catch (IOException expected) { 2740faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath } 2741faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath } 2742faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath 2743faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath @Test public void fullyBufferedPostIsTooLong() throws Exception { 2744faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath server.enqueue(new MockResponse().setBody("A")); 2745faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath 27463c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/b")); 2747faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath connection.setRequestProperty("Content-Length", "3"); 2748faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath connection.setRequestMethod("POST"); 2749faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath OutputStream out = connection.getOutputStream(); 2750faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath out.write('a'); 2751faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath out.write('b'); 2752faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath out.write('c'); 2753faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath try { 2754faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath out.write('d'); 27553c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller out.flush(); 2756faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath fail(); 2757faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath } catch (IOException expected) { 2758faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath } 2759faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath } 2760faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath 276154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test @Ignore public void testPooledConnectionsDetectHttp10() { 276254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson // TODO: write a test that shows pooled connections detect HTTP/1.0 (vs. HTTP/1.1) 276354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson fail("TODO"); 276454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 276554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 276654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test @Ignore public void postBodiesRetransmittedOnAuthProblems() { 276754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson fail("TODO"); 276854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 276954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 277054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test @Ignore public void cookiesAndTrailers() { 277154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson // Do cookie headers get processed too many times? 277254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson fail("TODO"); 277354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 277454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 277554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test @Ignore public void headerNamesContainingNullCharacter() { 277654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson // This is relevant for SPDY 277754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson fail("TODO"); 277854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 277954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 278054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test @Ignore public void headerValuesContainingNullCharacter() { 278154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson // This is relevant for SPDY 278254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson fail("TODO"); 278354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 278454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 2785faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath @Test public void emptyRequestHeaderValueIsAllowed() throws Exception { 2786faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath server.enqueue(new MockResponse().setBody("body")); 27873c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/")); 27883c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection.addRequestProperty("B", ""); 27893c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertContent("body", connection); 27903c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals("", connection.getRequestProperty("B")); 279154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 279254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 2793faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath @Test public void emptyResponseHeaderValueIsAllowed() throws Exception { 2794faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath server.enqueue(new MockResponse().addHeader("A:").setBody("body")); 27953c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/")); 27963c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertContent("body", connection); 27973c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals("", connection.getHeaderField("A")); 2798faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath } 2799faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath 2800faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath @Test public void emptyRequestHeaderNameIsStrict() throws Exception { 2801faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath server.enqueue(new MockResponse().setBody("body")); 28023c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/")); 2803faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath try { 28043c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection.setRequestProperty("", "A"); 2805faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath fail(); 2806faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath } catch (IllegalArgumentException expected) { 2807faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath } 2808faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath } 2809faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath 2810faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath @Test public void emptyResponseHeaderNameIsLenient() throws Exception { 2811e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Headers.Builder headers = new Headers.Builder(); 2812e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Internal.instance.addLenient(headers, ":A"); 2813e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse().setHeaders(headers.build()).setBody("body")); 28143c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/")); 28153c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection.getResponseCode(); 28163c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals("A", connection.getHeaderField("")); 28176c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer connection.getInputStream().close(); 281854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 281954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 282071b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller @Test public void requestHeaderValidationIsStrict() throws Exception { 282171b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller connection = client.open(server.getUrl("/")); 282271b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller try { 282371b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller connection.addRequestProperty("a\tb", "Value"); 282471b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller fail(); 282571b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller } catch (IllegalArgumentException expected) { 282671b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller } 282771b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller try { 282871b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller connection.addRequestProperty("Name", "c\u007fd"); 282971b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller fail(); 283071b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller } catch (IllegalArgumentException expected) { 283171b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller } 283271b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller try { 283371b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller connection.addRequestProperty("", "Value"); 283471b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller fail(); 283571b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller } catch (IllegalArgumentException expected) { 283671b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller } 283771b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller try { 283871b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller connection.addRequestProperty("\ud83c\udf69", "Value"); 283971b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller fail(); 284071b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller } catch (IllegalArgumentException expected) { 284171b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller } 284286a4f0d3830d797f7e915c7aa7b3fde524e5cad4Neil Fuller 284386a4f0d3830d797f7e915c7aa7b3fde524e5cad4Neil Fuller // ANDROID-BEGIN Disabled for http://b/28867041 284486a4f0d3830d797f7e915c7aa7b3fde524e5cad4Neil Fuller // try { 284586a4f0d3830d797f7e915c7aa7b3fde524e5cad4Neil Fuller // connection.addRequestProperty("Name", "\u2615\ufe0f"); 284686a4f0d3830d797f7e915c7aa7b3fde524e5cad4Neil Fuller // fail(); 284786a4f0d3830d797f7e915c7aa7b3fde524e5cad4Neil Fuller // } catch (IllegalArgumentException expected) { 284886a4f0d3830d797f7e915c7aa7b3fde524e5cad4Neil Fuller // } 284986a4f0d3830d797f7e915c7aa7b3fde524e5cad4Neil Fuller // ANDROID-END 285071b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller } 285171b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller 285271b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller @Test public void responseHeaderParsingIsLenient() throws Exception { 285371b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller Headers headers = new Headers.Builder() 285471b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller .add("Content-Length", "0") 285571b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller .addLenient("a\tb: c\u007fd") 285671b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller .addLenient(": ef") 285771b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller .addLenient("\ud83c\udf69: \u2615\ufe0f") 285871b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller .build(); 285971b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller server.enqueue(new MockResponse().setHeaders(headers)); 286071b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller 286171b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller connection = client.open(server.getUrl("/")); 286271b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller connection.getResponseCode(); 286371b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller assertEquals("c\u007fd", connection.getHeaderField("a\tb")); 286471b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller assertEquals("\u2615\ufe0f", connection.getHeaderField("\ud83c\udf69")); 286571b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller assertEquals("ef", connection.getHeaderField("")); 286671b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller } 286771b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller 286854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test @Ignore public void deflateCompression() { 286954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson fail("TODO"); 287054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 287154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 287254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test @Ignore public void postBodiesRetransmittedOnIpAddressProblems() { 287354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson fail("TODO"); 287454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 287554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 287654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Test @Ignore public void pooledConnectionProblemsNotReportedToProxySelector() { 287754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson fail("TODO"); 287854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 287954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 2880e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void customBasicAuthenticator() throws Exception { 2881faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath MockResponse pleaseAuthenticate = new MockResponse().setResponseCode(401) 2882faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath .addHeader("WWW-Authenticate: Basic realm=\"protected area\"") 2883faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath .setBody("Please authenticate."); 2884faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath server.enqueue(pleaseAuthenticate); 2885faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath server.enqueue(new MockResponse().setBody("A")); 2886faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath 2887e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller String credential = Credentials.basic("jesse", "peanutbutter"); 2888faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath RecordingOkAuthenticator authenticator = new RecordingOkAuthenticator(credential); 2889e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setAuthenticator(authenticator); 2890faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath assertContent("A", client.open(server.getUrl("/private"))); 2891faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath 2892e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertNull(server.takeRequest().getHeader("Authorization")); 2893e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(credential, server.takeRequest().getHeader("Authorization")); 2894faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath 2895f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller assertEquals(Proxy.NO_PROXY, authenticator.onlyProxy()); 2896e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Response response = authenticator.onlyResponse(); 2897e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("/private", response.request().url().getPath()); 2898e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(Arrays.asList(new Challenge("Basic", "protected area")), response.challenges()); 2899faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath } 2900faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath 2901e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void customTokenAuthenticator() throws Exception { 2902e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller MockResponse pleaseAuthenticate = new MockResponse().setResponseCode(401) 2903e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("WWW-Authenticate: Bearer realm=\"oauthed\"") 2904e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody("Please authenticate."); 2905e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(pleaseAuthenticate); 2906e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse().setBody("A")); 2907e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 2908e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller RecordingOkAuthenticator authenticator = new RecordingOkAuthenticator("oauthed abc123"); 2909e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setAuthenticator(authenticator); 2910e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertContent("A", client.open(server.getUrl("/private"))); 2911e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 2912e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertNull(server.takeRequest().getHeader("Authorization")); 2913e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("oauthed abc123", server.takeRequest().getHeader("Authorization")); 2914e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 2915e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Response response = authenticator.onlyResponse(); 2916e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("/private", response.request().url().getPath()); 2917e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(Arrays.asList(new Challenge("Bearer", "oauthed")), response.challenges()); 29183c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 29193c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 2920e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void authenticateCallsTrackedAsRedirects() throws Exception { 2921e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 2922e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setResponseCode(302) 2923e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("Location: /b")); 2924e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse() 2925e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setResponseCode(401) 2926e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .addHeader("WWW-Authenticate: Basic realm=\"protected area\"")); 2927e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse().setBody("c")); 2928e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 2929e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller RecordingOkAuthenticator authenticator = new RecordingOkAuthenticator( 2930e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Credentials.basic("jesse", "peanutbutter")); 2931e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setAuthenticator(authenticator); 2932e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertContent("c", client.open(server.getUrl("/a"))); 2933e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 2934e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Response challengeResponse = authenticator.responses.get(0); 2935e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("/b", challengeResponse.request().url().getPath()); 2936e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 2937e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Response redirectedBy = challengeResponse.priorResponse(); 2938e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("/a", redirectedBy.request().url().getPath()); 2939e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 2940e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 2941e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void attemptAuthorization20Times() throws Exception { 2942e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller for (int i = 0; i < 20; i++) { 2943e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse().setResponseCode(401)); 2944e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 2945e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse().setBody("Success!")); 2946e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 2947e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller String credential = Credentials.basic("jesse", "peanutbutter"); 2948e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setAuthenticator(new RecordingOkAuthenticator(credential)); 2949e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 2950e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller connection = client.open(server.getUrl("/0")); 2951e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertContent("Success!", connection); 29523c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 29533c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 2954e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void doesNotAttemptAuthorization21Times() throws Exception { 2955e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller for (int i = 0; i < 21; i++) { 2956e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse().setResponseCode(401)); 2957e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 2958e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 2959e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller String credential = Credentials.basic("jesse", "peanutbutter"); 2960e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setAuthenticator(new RecordingOkAuthenticator(credential)); 2961e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 2962e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller connection = client.open(server.getUrl("/")); 2963e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller try { 2964e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller connection.getInputStream(); 2965e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller fail(); 2966e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } catch (ProtocolException expected) { 2967e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(401, connection.getResponseCode()); 2968e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("Too many follow-up requests: 21", expected.getMessage()); 2969e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 2970e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 2971e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 2972e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void setsNegotiatedProtocolHeader_SPDY_3() throws Exception { 2973e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller setsNegotiatedProtocolHeader(Protocol.SPDY_3); 2974e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 2975e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 2976e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void setsNegotiatedProtocolHeader_HTTP_2() throws Exception { 2977e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller setsNegotiatedProtocolHeader(Protocol.HTTP_2); 2978e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 2979e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 2980e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller private void setsNegotiatedProtocolHeader(Protocol protocol) throws IOException { 2981e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller enableProtocol(protocol); 2982faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath server.enqueue(new MockResponse().setBody("A")); 2983e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setProtocols(Arrays.asList(protocol, Protocol.HTTP_1_1)); 29843c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/")); 29853c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller List<String> protocolValues = connection.getHeaderFields().get(SELECTED_PROTOCOL); 2986e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(Arrays.asList(protocol.toString()), protocolValues); 29873c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertContent("A", connection); 29883c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 29893c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 2990e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void http10SelectedProtocol() throws Exception { 2991e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse().setStatus("HTTP/1.0 200 OK")); 2992e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller connection = client.open(server.getUrl("/")); 2993e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller List<String> protocolValues = connection.getHeaderFields().get(SELECTED_PROTOCOL); 2994e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(Arrays.asList("http/1.0"), protocolValues); 2995e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 2996e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 2997e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void http11SelectedProtocol() throws Exception { 2998e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse().setStatus("HTTP/1.1 200 OK")); 2999e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller connection = client.open(server.getUrl("/")); 3000e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller List<String> protocolValues = connection.getHeaderFields().get(SELECTED_PROTOCOL); 3001e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(Arrays.asList("http/1.1"), protocolValues); 3002e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 3003e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 30043c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller /** For example, empty Protobuf RPC messages end up as a zero-length POST. */ 30053c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Test public void zeroLengthPost() throws IOException, InterruptedException { 30063c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller zeroLengthPayload("POST"); 30073c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 30083c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 30093c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Test public void zeroLengthPost_SPDY_3() throws Exception { 3010e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller enableProtocol(Protocol.SPDY_3); 30113c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller zeroLengthPost(); 30123c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 30133c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 30143c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Test public void zeroLengthPost_HTTP_2() throws Exception { 3015e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller enableProtocol(Protocol.HTTP_2); 30163c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller zeroLengthPost(); 30173c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 30183c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 30193c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller /** For example, creating an Amazon S3 bucket ends up as a zero-length POST. */ 30203c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Test public void zeroLengthPut() throws IOException, InterruptedException { 30213c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller zeroLengthPayload("PUT"); 30223c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 30233c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 30243c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Test public void zeroLengthPut_SPDY_3() throws Exception { 3025e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller enableProtocol(Protocol.SPDY_3); 30263c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller zeroLengthPut(); 30273c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 30283c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 30293c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Test public void zeroLengthPut_HTTP_2() throws Exception { 3030e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller enableProtocol(Protocol.HTTP_2); 30313c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller zeroLengthPut(); 30323c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 30333c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 30343c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller private void zeroLengthPayload(String method) 30353c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller throws IOException, InterruptedException { 30363c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller server.enqueue(new MockResponse()); 30373c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/")); 30383c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection.setRequestProperty("Content-Length", "0"); 30393c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection.setRequestMethod(method); 30403c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection.setFixedLengthStreamingMode(0); 30413c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection.setDoOutput(true); 30423c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertContent("", connection); 30433c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller RecordedRequest zeroLengthPayload = server.takeRequest(); 30443c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals(method, zeroLengthPayload.getMethod()); 30453c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals("0", zeroLengthPayload.getHeader("content-length")); 30463c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals(0L, zeroLengthPayload.getBodySize()); 30473c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 30483c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 3049e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void unspecifiedRequestBodyContentTypeGetsDefault() throws Exception { 3050e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse()); 3051e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 3052e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller connection = client.open(server.getUrl("/")); 3053e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller connection.setDoOutput(true); 3054e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller connection.getOutputStream().write("abc".getBytes(UTF_8)); 3055e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(200, connection.getResponseCode()); 3056e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 3057e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller RecordedRequest request = server.takeRequest(); 3058e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("application/x-www-form-urlencoded", request.getHeader("Content-Type")); 3059e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("3", request.getHeader("Content-Length")); 3060e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("abc", request.getBody().readUtf8()); 3061e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 3062e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 30633c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Test public void setProtocols() throws Exception { 30643c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller server.enqueue(new MockResponse().setBody("A")); 3065e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setProtocols(Arrays.asList(Protocol.HTTP_1_1)); 3066faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath assertContent("A", client.open(server.getUrl("/"))); 3067faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath } 3068faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath 30693c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Test public void setProtocolsWithoutHttp11() throws Exception { 3070faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath try { 3071e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setProtocols(Arrays.asList(Protocol.SPDY_3)); 3072faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath fail(); 3073faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath } catch (IllegalArgumentException expected) { 3074faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath } 3075faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath } 3076faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath 30773c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Test public void setProtocolsWithNull() throws Exception { 3078faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath try { 3079e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setProtocols(Arrays.asList(Protocol.HTTP_1_1, null)); 3080faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath fail(); 3081faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath } catch (IllegalArgumentException expected) { 3082faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath } 3083faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath } 3084faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath 3085a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath @Test public void veryLargeFixedLengthRequest() throws Exception { 308671b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller server.setBodyLimit(0); 3087a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath server.enqueue(new MockResponse()); 3088a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath 30893c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection = client.open(server.getUrl("/")); 3090a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath connection.setDoOutput(true); 3091a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath long contentLength = Integer.MAX_VALUE + 1L; 3092a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath connection.setFixedLengthStreamingMode(contentLength); 3093a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath OutputStream out = connection.getOutputStream(); 3094a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath byte[] buffer = new byte[1024 * 1024]; 3095a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath for (long bytesWritten = 0; bytesWritten < contentLength; ) { 3096a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath int byteCount = (int) Math.min(buffer.length, contentLength - bytesWritten); 3097a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath out.write(buffer, 0, byteCount); 3098a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath bytesWritten += byteCount; 3099a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath } 3100a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath assertContent("", connection); 3101a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath 3102a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath RecordedRequest request = server.takeRequest(); 3103a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath assertEquals(Long.toString(contentLength), request.getHeader("Content-Length")); 3104a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath } 3105a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath 31063c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller /** 31073c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * We had a bug where we attempted to gunzip responses that didn't have a 31083c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * body. This only came up with 304s since that response code can include 31093c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * headers (like "Content-Encoding") without any content to go along with it. 31103c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * https://github.com/square/okhttp/issues/358 31113c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller */ 31123c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Test public void noTransparentGzipFor304NotModified() throws Exception { 31133c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller server.enqueue(new MockResponse() 31143c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller .clearHeaders() 31153c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED) 31163c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller .addHeader("Content-Encoding: gzip")); 31173c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller server.enqueue(new MockResponse().setBody("b")); 31183c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 31193c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller HttpURLConnection connection1 = client.open(server.getUrl("/")); 31203c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals(HttpURLConnection.HTTP_NOT_MODIFIED, connection1.getResponseCode()); 31213c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertContent("", connection1); 31223c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 31233c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller HttpURLConnection connection2 = client.open(server.getUrl("/")); 31243c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals(HttpURLConnection.HTTP_OK, connection2.getResponseCode()); 31253c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertContent("b", connection2); 31263c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 31273c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller RecordedRequest requestA = server.takeRequest(); 31283c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals(0, requestA.getSequenceNumber()); 31293c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 31303c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller RecordedRequest requestB = server.takeRequest(); 31313c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals(1, requestB.getSequenceNumber()); 31323c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 31333c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 31343c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller /** 31353c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * We had a bug where we weren't closing Gzip streams on redirects. 31363c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * https://github.com/square/okhttp/issues/441 31373c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller */ 31383c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Test public void gzipWithRedirectAndConnectionReuse() throws Exception { 31393c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller server.enqueue(new MockResponse() 31403c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller .setResponseCode(HttpURLConnection.HTTP_MOVED_TEMP) 31413c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller .addHeader("Location: /foo") 31423c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller .addHeader("Content-Encoding: gzip") 3143e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller .setBody(gzip("Moved! Moved! Moved!"))); 31443c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller server.enqueue(new MockResponse().setBody("This is the new page!")); 31453c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 31463c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller HttpURLConnection connection = client.open(server.getUrl("/")); 31473c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertContent("This is the new page!", connection); 31483c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 31493c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller RecordedRequest requestA = server.takeRequest(); 31503c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals(0, requestA.getSequenceNumber()); 31513c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 31523c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller RecordedRequest requestB = server.takeRequest(); 31533c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals(1, requestB.getSequenceNumber()); 31543c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 31553c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 31563c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller /** 31573c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * The RFC is unclear in this regard as it only specifies that this should 31583c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * invalidate the cache entry (if any). 31593c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller */ 31603c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Test public void bodyPermittedOnDelete() throws Exception { 31613c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller server.enqueue(new MockResponse()); 31623c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 31633c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller HttpURLConnection connection = client.open(server.getUrl("/")); 31643c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection.setRequestMethod("DELETE"); 31653c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection.setDoOutput(true); 31663c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller connection.getOutputStream().write("BODY".getBytes(UTF_8)); 31673c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals(200, connection.getResponseCode()); 31683c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 31693c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller RecordedRequest request = server.takeRequest(); 31703c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller assertEquals("DELETE", request.getMethod()); 3171e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("BODY", request.getBody().readUtf8()); 3172e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 3173e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 3174e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void userAgentPicksUpHttpAgentSystemProperty() throws Exception { 3175e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse().setBody("abc")); 3176e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 3177e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller System.setProperty("http.agent", "foo"); 3178e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertContent("abc", client.open(server.getUrl("/"))); 3179e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 3180e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller RecordedRequest request = server.takeRequest(); 3181e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals("foo", request.getHeader("User-Agent")); 3182e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 3183e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 318471b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller /** https://github.com/square/okhttp/issues/891 */ 318571b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller @Test public void userAgentSystemPropertyIsNotAscii() throws Exception { 3186e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse().setBody("abc")); 3187e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 318871b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller System.setProperty("http.agent", "a\nb\ud83c\udf69c\ud83c\udf68d\u007fe"); 3189e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertContent("abc", client.open(server.getUrl("/"))); 3190e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 3191e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller RecordedRequest request = server.takeRequest(); 319271b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller assertEquals("a?b?c?d?e", request.getHeader("User-Agent")); 319371b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller } 319471b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller 319571b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller @Test public void userAgentDefaultsToOkHttpVersion() throws Exception { 319671b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller server.enqueue(new MockResponse().setBody("abc")); 319771b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller 319871b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller assertContent("abc", client.open(server.getUrl("/"))); 319971b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller 320071b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller RecordedRequest request = server.takeRequest(); 320171b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller assertEquals(Version.userAgent(), request.getHeader("User-Agent")); 3202e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 3203e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 3204e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void interceptorsNotInvoked() throws Exception { 3205e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Interceptor interceptor = new Interceptor() { 3206e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Override public Response intercept(Chain chain) throws IOException { 3207e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller throw new AssertionError(); 3208e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 3209e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller }; 3210e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().interceptors().add(interceptor); 3211e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().networkInterceptors().add(interceptor); 3212e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 3213e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller server.enqueue(new MockResponse().setBody("abc")); 3214e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertContent("abc", client.open(server.getUrl("/"))); 32153c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 32163c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 321771b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller @Test public void urlWithSpaceInHost() throws Exception { 321871b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller URLConnection urlConnection = client.open(new URL("http://and roid.com/")); 321971b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller try { 322071b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller urlConnection.getInputStream(); 322171b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller fail(); 322271b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller } catch (UnknownHostException expected) { 322371b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller } 322471b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller } 322571b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller 322671b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller @Test public void urlWithSpaceInHostViaHttpProxy() throws Exception { 322771b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller server.enqueue(new MockResponse()); 322871b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller URLConnection urlConnection = 322971b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller client.open(new URL("http://and roid.com/"), server.toProxyAddress()); 323071b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller 323171b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller try { 323271b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller // This test is to check that a NullPointerException is not thrown. 323371b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller urlConnection.getInputStream(); 323471b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller fail(); // the RI makes a bogus proxy request for "GET http://and roid.com/ HTTP/1.1" 323571b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller } catch (UnknownHostException expected) { 323671b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller } 323771b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller } 323871b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller 323971b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller @Test public void urlHostWithNul() throws Exception { 324071b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller URLConnection urlConnection = client.open(new URL("http://host\u0000/")); 324171b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller try { 324271b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller urlConnection.getInputStream(); 324371b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller fail(); 324471b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller } catch (UnknownHostException expected) { 324571b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller } 324671b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller } 324771b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller 324871b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller @Test public void urlRedirectToHostWithNul() throws Exception { 324971b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller String redirectUrl = "http://host\u0000/"; 325071b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller server.enqueue(new MockResponse().setResponseCode(302) 325171b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller .addHeaderLenient("Location", redirectUrl)); 325271b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller 325371b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller HttpURLConnection urlConnection = client.open(server.getUrl("/")); 325471b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller assertEquals(302, urlConnection.getResponseCode()); 325571b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller assertEquals(redirectUrl, urlConnection.getHeaderField("Location")); 325671b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller } 325771b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller 325871b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller @Test public void urlWithBadAsciiHost() throws Exception { 325971b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller URLConnection urlConnection = client.open(new URL("http://host\u0001/")); 326071b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller try { 326171b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller urlConnection.getInputStream(); 326271b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller fail(); 326371b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller } catch (UnknownHostException expected) { 326471b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller } 326571b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller } 326671b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller 3267c4c05ff9964ac8bca83bc751abe551f515ca499aNeil Fuller @Test public void instanceFollowsRedirects() throws Exception { 3268ceafaf318f1176d96d18ed04355f76fa91a8e12bNeil Fuller testInstanceFollowsRedirects("http://www.google.com/"); 3269ceafaf318f1176d96d18ed04355f76fa91a8e12bNeil Fuller testInstanceFollowsRedirects("https://www.google.com/"); 3270ceafaf318f1176d96d18ed04355f76fa91a8e12bNeil Fuller } 3271ceafaf318f1176d96d18ed04355f76fa91a8e12bNeil Fuller 3272ceafaf318f1176d96d18ed04355f76fa91a8e12bNeil Fuller private void testInstanceFollowsRedirects(String spec) throws Exception { 3273ceafaf318f1176d96d18ed04355f76fa91a8e12bNeil Fuller URL url = new URL(spec); 3274ceafaf318f1176d96d18ed04355f76fa91a8e12bNeil Fuller HttpURLConnection urlConnection = client.open(url); 3275ceafaf318f1176d96d18ed04355f76fa91a8e12bNeil Fuller urlConnection.setInstanceFollowRedirects(true); 3276ceafaf318f1176d96d18ed04355f76fa91a8e12bNeil Fuller assertTrue(urlConnection.getInstanceFollowRedirects()); 3277ceafaf318f1176d96d18ed04355f76fa91a8e12bNeil Fuller urlConnection.setInstanceFollowRedirects(false); 3278ceafaf318f1176d96d18ed04355f76fa91a8e12bNeil Fuller assertFalse(urlConnection.getInstanceFollowRedirects()); 3279ceafaf318f1176d96d18ed04355f76fa91a8e12bNeil Fuller } 3280ceafaf318f1176d96d18ed04355f76fa91a8e12bNeil Fuller 328154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson /** Returns a gzipped copy of {@code bytes}. */ 3282e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller public Buffer gzip(String data) throws IOException { 3283e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Buffer result = new Buffer(); 3284e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller BufferedSink gzipSink = Okio.buffer(new GzipSink(result)); 3285e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller gzipSink.writeUtf8(data); 3286e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller gzipSink.close(); 3287e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller return result; 328854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 328954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 329054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson /** 329154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson * Reads at most {@code limit} characters from {@code in} and asserts that 329254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson * content equals {@code expected}. 329354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson */ 32943c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller private void assertContent(String expected, HttpURLConnection connection, int limit) 329554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson throws IOException { 329654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson connection.connect(); 329754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertEquals(expected, readAscii(connection.getInputStream(), limit)); 329854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 329954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 33003c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller private void assertContent(String expected, HttpURLConnection connection) throws IOException { 330154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson assertContent(expected, connection, Integer.MAX_VALUE); 330254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 330354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 330454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson private Set<String> newSet(String... elements) { 330571b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller return new LinkedHashSet<>(Arrays.asList(elements)); 330654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 330754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 330854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson enum TransferKind { 330954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson CHUNKED() { 3310e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Override void setBody(MockResponse response, Buffer content, int chunkSize) 331154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson throws IOException { 331254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson response.setChunkedBody(content, chunkSize); 331354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 331454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Override void setForRequest(HttpURLConnection connection, int contentLength) { 331554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson connection.setChunkedStreamingMode(5); 331654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 331754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson }, 331854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson FIXED_LENGTH() { 3319e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Override void setBody(MockResponse response, Buffer content, int chunkSize) { 332054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson response.setBody(content); 332154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 332254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Override void setForRequest(HttpURLConnection connection, int contentLength) { 3323faf49723fb689c626f69876e718c58018eff8ee7Narayan Kamath connection.setFixedLengthStreamingMode(contentLength); 332454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 332554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson }, 332654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson END_OF_STREAM() { 3327e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Override void setBody(MockResponse response, Buffer content, int chunkSize) { 332854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson response.setBody(content); 332954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson response.setSocketPolicy(DISCONNECT_AT_END); 3330e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller response.removeHeader("Content-Length"); 333154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 333254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Override void setForRequest(HttpURLConnection connection, int contentLength) { 333354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 333454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson }; 333554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 3336e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller abstract void setBody(MockResponse response, Buffer content, int chunkSize) throws IOException; 333754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 333854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson abstract void setForRequest(HttpURLConnection connection, int contentLength); 333954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 334054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson void setBody(MockResponse response, String content, int chunkSize) throws IOException { 3341e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller setBody(response, new Buffer().writeUtf8(content), chunkSize); 334254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 334354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 334454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 334554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson enum ProxyConfig { 334654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson NO_PROXY() { 3347e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Override public HttpURLConnection connect( 3348e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller MockWebServer server, OkUrlFactory streamHandlerFactory, URL url) 334954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson throws IOException { 3350e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller streamHandlerFactory.client().setProxy(Proxy.NO_PROXY); 3351e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller return streamHandlerFactory.open(url); 335254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 335354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson }, 335454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson 335554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson CREATE_ARG() { 3356e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Override public HttpURLConnection connect( 3357e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller MockWebServer server, OkUrlFactory streamHandlerFactory, URL url) 335854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson throws IOException { 3359e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller streamHandlerFactory.client().setProxy(server.toProxyAddress()); 3360e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller return streamHandlerFactory.open(url); 336154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 336254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson }, 3363c3f6f16bd4a2338e88275641b9f2f56e816ca377Narayan Kamath 336454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson PROXY_SYSTEM_PROPERTY() { 3365e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Override public HttpURLConnection connect( 3366e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller MockWebServer server, OkUrlFactory streamHandlerFactory, URL url) 336754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson throws IOException { 3368e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller System.setProperty("proxyHost", server.getHostName()); 336954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson System.setProperty("proxyPort", Integer.toString(server.getPort())); 3370e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller return streamHandlerFactory.open(url); 337154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 337254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson }, 3373c3f6f16bd4a2338e88275641b9f2f56e816ca377Narayan Kamath 337454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson HTTP_PROXY_SYSTEM_PROPERTY() { 3375e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Override public HttpURLConnection connect( 3376e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller MockWebServer server, OkUrlFactory streamHandlerFactory, URL url) 337754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson throws IOException { 3378e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller System.setProperty("http.proxyHost", server.getHostName()); 337954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson System.setProperty("http.proxyPort", Integer.toString(server.getPort())); 3380e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller return streamHandlerFactory.open(url); 338154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 338254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson }, 3383c3f6f16bd4a2338e88275641b9f2f56e816ca377Narayan Kamath 338454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson HTTPS_PROXY_SYSTEM_PROPERTY() { 3385e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Override public HttpURLConnection connect( 3386e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller MockWebServer server, OkUrlFactory streamHandlerFactory, URL url) 338754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson throws IOException { 3388e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller System.setProperty("https.proxyHost", server.getHostName()); 338954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson System.setProperty("https.proxyPort", Integer.toString(server.getPort())); 3390e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller return streamHandlerFactory.open(url); 339154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 339254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson }; 3393c3f6f16bd4a2338e88275641b9f2f56e816ca377Narayan Kamath 3394e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller public abstract HttpURLConnection connect( 3395e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller MockWebServer server, OkUrlFactory streamHandlerFactory, URL url) 339654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson throws IOException; 339754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 3398c3f6f16bd4a2338e88275641b9f2f56e816ca377Narayan Kamath 339954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson private static class RecordingTrustManager implements X509TrustManager { 340054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson private final List<String> calls = new ArrayList<String>(); 34016c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer private final X509TrustManager delegate; 34026c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer 34036c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer public RecordingTrustManager(SSLContext sslContext) { 34046c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer this.delegate = Platform.get().trustManager(sslContext.getSocketFactory()); 34056c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer } 34062231db3e6bb54447a9b14cf004a6cb03c373651cjwilson 340754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson public X509Certificate[] getAcceptedIssuers() { 34086c251e20f00c7574b217bd4351ac81666f574380Tobias Thierer return delegate.getAcceptedIssuers(); 3409c3f6f16bd4a2338e88275641b9f2f56e816ca377Narayan Kamath } 3410c3f6f16bd4a2338e88275641b9f2f56e816ca377Narayan Kamath 341154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson public void checkClientTrusted(X509Certificate[] chain, String authType) 341254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson throws CertificateException { 341354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson calls.add("checkClientTrusted " + certificatesToString(chain)); 3414c3f6f16bd4a2338e88275641b9f2f56e816ca377Narayan Kamath } 3415c3f6f16bd4a2338e88275641b9f2f56e816ca377Narayan Kamath 341654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson public void checkServerTrusted(X509Certificate[] chain, String authType) 341754cf3446000fdcf88a9e62724f7deb0282e98da1jwilson throws CertificateException { 341854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson calls.add("checkServerTrusted " + certificatesToString(chain)); 3419c3f6f16bd4a2338e88275641b9f2f56e816ca377Narayan Kamath } 3420c3f6f16bd4a2338e88275641b9f2f56e816ca377Narayan Kamath 342154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson private String certificatesToString(X509Certificate[] certificates) { 342254cf3446000fdcf88a9e62724f7deb0282e98da1jwilson List<String> result = new ArrayList<String>(); 342354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson for (X509Certificate certificate : certificates) { 342454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson result.add(certificate.getSubjectDN() + " " + certificate.getSerialNumber()); 342554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 342654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson return result.toString(); 3427c3f6f16bd4a2338e88275641b9f2f56e816ca377Narayan Kamath } 342854cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 34297899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 343054cf3446000fdcf88a9e62724f7deb0282e98da1jwilson private static class FakeProxySelector extends ProxySelector { 3431e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller List<Proxy> proxies = new ArrayList<>(); 34327899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 343354cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Override public List<Proxy> select(URI uri) { 343454cf3446000fdcf88a9e62724f7deb0282e98da1jwilson // Don't handle 'socket' schemes, which the RI's Socket class may request (for SOCKS). 343554cf3446000fdcf88a9e62724f7deb0282e98da1jwilson return uri.getScheme().equals("http") || uri.getScheme().equals("https") ? proxies 343654cf3446000fdcf88a9e62724f7deb0282e98da1jwilson : Collections.singletonList(Proxy.NO_PROXY); 34377899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 34382231db3e6bb54447a9b14cf004a6cb03c373651cjwilson 343954cf3446000fdcf88a9e62724f7deb0282e98da1jwilson @Override public void connectFailed(URI uri, SocketAddress sa, IOException ioe) { 34402231db3e6bb54447a9b14cf004a6cb03c373651cjwilson } 344154cf3446000fdcf88a9e62724f7deb0282e98da1jwilson } 34423c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 34433c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller /** 34443c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * Tests that use this will fail unless boot classpath is set. Ex. {@code 3445e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * -Xbootclasspath/p:/tmp/alpn-boot-8.0.0.v20140317} 3446e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller */ 3447e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller private void enableProtocol(Protocol protocol) { 3448e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setSslSocketFactory(sslContext.getSocketFactory()); 3449e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setHostnameVerifier(new RecordingHostnameVerifier()); 3450e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.client().setProtocols(Arrays.asList(protocol, Protocol.HTTP_1_1)); 345171b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller server.useHttps(sslContext.getSocketFactory(), false); 345271b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller server.setProtocolNegotiationEnabled(true); 345371b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller server.setProtocols(client.client().getProtocols()); 3454e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 3455e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 3456e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller /** 3457e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * Used during tests that involve TLS connection fallback attempts. OkHttp includes the 3458e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * TLS_FALLBACK_SCSV cipher on fallback connections. See 3459e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * {@link com.squareup.okhttp.FallbackTestClientSocketFactory} for details. 34603c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller */ 346171b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller private void suppressTlsFallbackScsv(OkHttpClient client) { 3462e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller FallbackTestClientSocketFactory clientSocketFactory = 3463e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller new FallbackTestClientSocketFactory(sslContext.getSocketFactory()); 3464e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller client.setSslSocketFactory(clientSocketFactory); 34653c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 3466c3f6f16bd4a2338e88275641b9f2f56e816ca377Narayan Kamath} 3467