mirror of
https://github.com/square/okhttp.git
synced 2025-08-08 23:42:08 +03:00
Create request/response API tests to match some URLConnectionTest tests.
This is more work towards being able to later delete HttpURLConnectionImpl without losing test coverage. Also do some test cleanup.
This commit is contained in:
@@ -38,7 +38,7 @@ import okhttp3.internal.InternalCache;
|
|||||||
import okhttp3.internal.SslContextBuilder;
|
import okhttp3.internal.SslContextBuilder;
|
||||||
import okhttp3.mockwebserver.MockResponse;
|
import okhttp3.mockwebserver.MockResponse;
|
||||||
import okhttp3.mockwebserver.MockWebServer;
|
import okhttp3.mockwebserver.MockWebServer;
|
||||||
import okhttp3.testing.RecordingHostnameVerifier;
|
import okhttp3.RecordingHostnameVerifier;
|
||||||
import okio.Buffer;
|
import okio.Buffer;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
|
@@ -68,7 +68,7 @@ import okhttp3.mockwebserver.MockResponse;
|
|||||||
import okhttp3.mockwebserver.MockWebServer;
|
import okhttp3.mockwebserver.MockWebServer;
|
||||||
import okhttp3.mockwebserver.RecordedRequest;
|
import okhttp3.mockwebserver.RecordedRequest;
|
||||||
import okhttp3.mockwebserver.SocketPolicy;
|
import okhttp3.mockwebserver.SocketPolicy;
|
||||||
import okhttp3.testing.RecordingHostnameVerifier;
|
import okhttp3.RecordingHostnameVerifier;
|
||||||
import okio.Buffer;
|
import okio.Buffer;
|
||||||
import okio.BufferedSink;
|
import okio.BufferedSink;
|
||||||
import okio.GzipSink;
|
import okio.GzipSink;
|
||||||
|
@@ -13,7 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package okhttp3.internal.http;
|
package okhttp3;
|
||||||
|
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
@@ -21,7 +21,6 @@ import java.util.ArrayList;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import okhttp3.Dns;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
@@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2009 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package okhttp3;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.Proxy;
|
||||||
|
import java.net.ProxySelector;
|
||||||
|
import java.net.SocketAddress;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public final class FakeProxySelector extends ProxySelector {
|
||||||
|
public final List<Proxy> proxies = new ArrayList<>();
|
||||||
|
|
||||||
|
public FakeProxySelector addProxy(Proxy proxy) {
|
||||||
|
proxies.add(proxy);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public List<Proxy> select(URI uri) {
|
||||||
|
// Don't handle 'socket' schemes, which the RI's Socket class may request (for SOCKS).
|
||||||
|
return uri.getScheme().equals("http") || uri.getScheme().equals("https") ? proxies
|
||||||
|
: Collections.singletonList(Proxy.NO_PROXY);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {
|
||||||
|
}
|
||||||
|
}
|
@@ -14,7 +14,7 @@
|
|||||||
* License for the specific language governing permissions and limitations under
|
* License for the specific language governing permissions and limitations under
|
||||||
* the License.
|
* the License.
|
||||||
*/
|
*/
|
||||||
package okhttp3.internal.tls;
|
package okhttp3;
|
||||||
|
|
||||||
import java.security.Principal;
|
import java.security.Principal;
|
||||||
import java.security.cert.Certificate;
|
import java.security.cert.Certificate;
|
||||||
@@ -23,7 +23,7 @@ import javax.net.ssl.SSLSession;
|
|||||||
import javax.net.ssl.SSLSessionContext;
|
import javax.net.ssl.SSLSessionContext;
|
||||||
import javax.security.cert.X509Certificate;
|
import javax.security.cert.X509Certificate;
|
||||||
|
|
||||||
final class FakeSSLSession implements SSLSession {
|
public final class FakeSSLSession implements SSLSession {
|
||||||
private final Certificate[] certificates;
|
private final Certificate[] certificates;
|
||||||
|
|
||||||
public FakeSSLSession(Certificate... certificates) throws Exception {
|
public FakeSSLSession(Certificate... certificates) throws Exception {
|
@@ -13,7 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package okhttp3.testing;
|
package okhttp3;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
@@ -24,7 +24,6 @@ import java.net.HttpCookie;
|
|||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.net.ProtocolException;
|
|
||||||
import java.net.Proxy;
|
import java.net.Proxy;
|
||||||
import java.net.ServerSocket;
|
import java.net.ServerSocket;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
@@ -56,7 +55,6 @@ import okhttp3.internal.SingleInetAddressDns;
|
|||||||
import okhttp3.internal.SslContextBuilder;
|
import okhttp3.internal.SslContextBuilder;
|
||||||
import okhttp3.internal.Util;
|
import okhttp3.internal.Util;
|
||||||
import okhttp3.internal.Version;
|
import okhttp3.internal.Version;
|
||||||
import okhttp3.internal.http.FakeDns;
|
|
||||||
import okhttp3.internal.http.RecordingProxySelector;
|
import okhttp3.internal.http.RecordingProxySelector;
|
||||||
import okhttp3.internal.io.InMemoryFileSystem;
|
import okhttp3.internal.io.InMemoryFileSystem;
|
||||||
import okhttp3.mockwebserver.Dispatcher;
|
import okhttp3.mockwebserver.Dispatcher;
|
||||||
@@ -64,7 +62,6 @@ import okhttp3.mockwebserver.MockResponse;
|
|||||||
import okhttp3.mockwebserver.MockWebServer;
|
import okhttp3.mockwebserver.MockWebServer;
|
||||||
import okhttp3.mockwebserver.RecordedRequest;
|
import okhttp3.mockwebserver.RecordedRequest;
|
||||||
import okhttp3.mockwebserver.SocketPolicy;
|
import okhttp3.mockwebserver.SocketPolicy;
|
||||||
import okhttp3.testing.RecordingHostnameVerifier;
|
|
||||||
import okio.Buffer;
|
import okio.Buffer;
|
||||||
import okio.BufferedSink;
|
import okio.BufferedSink;
|
||||||
import okio.BufferedSource;
|
import okio.BufferedSource;
|
||||||
@@ -72,6 +69,7 @@ import okio.GzipSink;
|
|||||||
import okio.Okio;
|
import okio.Okio;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
|
import org.junit.Ignore;
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.rules.TestRule;
|
import org.junit.rules.TestRule;
|
||||||
@@ -113,12 +111,7 @@ public final class CallTest {
|
|||||||
@Test public void get() throws Exception {
|
@Test public void get() throws Exception {
|
||||||
server.enqueue(new MockResponse().setBody("abc").addHeader("Content-Type: text/plain"));
|
server.enqueue(new MockResponse().setBody("abc").addHeader("Content-Type: text/plain"));
|
||||||
|
|
||||||
Request request = new Request.Builder()
|
executeSynchronously("/", "User-Agent", "SyncApiTest")
|
||||||
.url(server.url("/"))
|
|
||||||
.header("User-Agent", "SyncApiTest")
|
|
||||||
.build();
|
|
||||||
|
|
||||||
executeSynchronously(request)
|
|
||||||
.assertCode(200)
|
.assertCode(200)
|
||||||
.assertSuccessful()
|
.assertSuccessful()
|
||||||
.assertHeader("Content-Type", "text/plain")
|
.assertHeader("Content-Type", "text/plain")
|
||||||
@@ -133,14 +126,7 @@ public final class CallTest {
|
|||||||
|
|
||||||
@Test public void buildRequestUsingHttpUrl() throws Exception {
|
@Test public void buildRequestUsingHttpUrl() throws Exception {
|
||||||
server.enqueue(new MockResponse());
|
server.enqueue(new MockResponse());
|
||||||
|
executeSynchronously("/").assertSuccessful();
|
||||||
HttpUrl httpUrl = server.url("/");
|
|
||||||
Request request = new Request.Builder()
|
|
||||||
.url(httpUrl)
|
|
||||||
.build();
|
|
||||||
assertEquals(httpUrl, request.url());
|
|
||||||
|
|
||||||
executeSynchronously(request).assertSuccessful();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test public void invalidScheme() throws Exception {
|
@Test public void invalidScheme() throws Exception {
|
||||||
@@ -165,12 +151,7 @@ public final class CallTest {
|
|||||||
|
|
||||||
@Test public void getReturns500() throws Exception {
|
@Test public void getReturns500() throws Exception {
|
||||||
server.enqueue(new MockResponse().setResponseCode(500));
|
server.enqueue(new MockResponse().setResponseCode(500));
|
||||||
|
executeSynchronously("/")
|
||||||
Request request = new Request.Builder()
|
|
||||||
.url(server.url("/"))
|
|
||||||
.build();
|
|
||||||
|
|
||||||
executeSynchronously(request)
|
|
||||||
.assertCode(500)
|
.assertCode(500)
|
||||||
.assertNotSuccessful();
|
.assertNotSuccessful();
|
||||||
}
|
}
|
||||||
@@ -195,13 +176,7 @@ public final class CallTest {
|
|||||||
.addHeader("B", "123")
|
.addHeader("B", "123")
|
||||||
.addHeader("B", "234"));
|
.addHeader("B", "234"));
|
||||||
|
|
||||||
Request request = new Request.Builder()
|
executeSynchronously("/", "A", "345", "A", "456")
|
||||||
.url(server.url("/"))
|
|
||||||
.addHeader("A", "345")
|
|
||||||
.addHeader("A", "456")
|
|
||||||
.build();
|
|
||||||
|
|
||||||
executeSynchronously(request)
|
|
||||||
.assertCode(200)
|
.assertCode(200)
|
||||||
.assertHeader("B", "123", "234");
|
.assertHeader("B", "123", "234");
|
||||||
|
|
||||||
@@ -410,8 +385,7 @@ public final class CallTest {
|
|||||||
.authenticator(new RecordingOkAuthenticator(credential))
|
.authenticator(new RecordingOkAuthenticator(credential))
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
Request request = new Request.Builder().url(server.url("/")).build();
|
executeSynchronously("/")
|
||||||
executeSynchronously(request)
|
|
||||||
.assertCode(200)
|
.assertCode(200)
|
||||||
.assertBody("Success!");
|
.assertBody("Success!");
|
||||||
}
|
}
|
||||||
@@ -675,14 +649,9 @@ public final class CallTest {
|
|||||||
server.enqueue(new MockResponse().setBody("def"));
|
server.enqueue(new MockResponse().setBody("def"));
|
||||||
server.enqueue(new MockResponse().setBody("ghi"));
|
server.enqueue(new MockResponse().setBody("ghi"));
|
||||||
|
|
||||||
executeSynchronously(new Request.Builder().url(server.url("/a")).build())
|
executeSynchronously("/a").assertBody("abc");
|
||||||
.assertBody("abc");
|
executeSynchronously("/b").assertBody("def");
|
||||||
|
executeSynchronously("/c").assertBody("ghi");
|
||||||
executeSynchronously(new Request.Builder().url(server.url("/b")).build())
|
|
||||||
.assertBody("def");
|
|
||||||
|
|
||||||
executeSynchronously(new Request.Builder().url(server.url("/c")).build())
|
|
||||||
.assertBody("ghi");
|
|
||||||
|
|
||||||
assertEquals(0, server.takeRequest().getSequenceNumber());
|
assertEquals(0, server.takeRequest().getSequenceNumber());
|
||||||
assertEquals(1, server.takeRequest().getSequenceNumber());
|
assertEquals(1, server.takeRequest().getSequenceNumber());
|
||||||
@@ -742,7 +711,7 @@ public final class CallTest {
|
|||||||
client = client.newBuilder()
|
client = client.newBuilder()
|
||||||
.readTimeout(1000, TimeUnit.MILLISECONDS)
|
.readTimeout(1000, TimeUnit.MILLISECONDS)
|
||||||
.build();
|
.build();
|
||||||
executeSynchronously(new Request.Builder().url(server.url("/a")).build()).assertBody("abc");
|
executeSynchronously("/a").assertBody("abc");
|
||||||
|
|
||||||
// Second request: time out after 250ms.
|
// Second request: time out after 250ms.
|
||||||
client = client.newBuilder()
|
client = client.newBuilder()
|
||||||
@@ -903,8 +872,7 @@ public final class CallTest {
|
|||||||
.setBody("abc")
|
.setBody("abc")
|
||||||
.addHeader("Content-Type: text/plain"));
|
.addHeader("Content-Type: text/plain"));
|
||||||
|
|
||||||
executeSynchronously(new Request.Builder().url(server.url("/")).build())
|
executeSynchronously("/").assertHandshake();
|
||||||
.assertHandshake();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test public void tls_Async() throws Exception {
|
@Test public void tls_Async() throws Exception {
|
||||||
@@ -931,9 +899,8 @@ public final class CallTest {
|
|||||||
.build();
|
.build();
|
||||||
assertTrue(client.retryOnConnectionFailure());
|
assertTrue(client.retryOnConnectionFailure());
|
||||||
|
|
||||||
Request request = new Request.Builder().url(server.url("/")).build();
|
executeSynchronously("/").assertBody("seed connection pool");
|
||||||
executeSynchronously(request).assertBody("seed connection pool");
|
executeSynchronously("/").assertBody("retry success");
|
||||||
executeSynchronously(request).assertBody("retry success");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test public void noRecoverWhenRetryOnConnectionFailureIsFalse() throws Exception {
|
@Test public void noRecoverWhenRetryOnConnectionFailureIsFalse() throws Exception {
|
||||||
@@ -946,14 +913,10 @@ public final class CallTest {
|
|||||||
.retryOnConnectionFailure(false)
|
.retryOnConnectionFailure(false)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
Request request = new Request.Builder().url(server.url("/")).build();
|
executeSynchronously("/").assertBody("seed connection pool");
|
||||||
executeSynchronously(request).assertBody("seed connection pool");
|
|
||||||
try {
|
|
||||||
// If this succeeds, too many requests were made.
|
// If this succeeds, too many requests were made.
|
||||||
client.newCall(request).execute();
|
executeSynchronously("/").assertFailure(IOException.class);
|
||||||
fail();
|
|
||||||
} catch (IOException expected) {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test public void recoverFromTlsHandshakeFailure() throws Exception {
|
@Test public void recoverFromTlsHandshakeFailure() throws Exception {
|
||||||
@@ -967,8 +930,7 @@ public final class CallTest {
|
|||||||
.sslSocketFactory(suppressTlsFallbackClientSocketFactory())
|
.sslSocketFactory(suppressTlsFallbackClientSocketFactory())
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
executeSynchronously(new Request.Builder().url(server.url("/")).build())
|
executeSynchronously("/").assertBody("abc");
|
||||||
.assertBody("abc");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test public void recoverFromTlsHandshakeFailure_tlsFallbackScsvEnabled() throws Exception {
|
@Test public void recoverFromTlsHandshakeFailure_tlsFallbackScsvEnabled() throws Exception {
|
||||||
@@ -1184,29 +1146,20 @@ public final class CallTest {
|
|||||||
|
|
||||||
// Store a response in the cache.
|
// Store a response in the cache.
|
||||||
HttpUrl url = server.url("/");
|
HttpUrl url = server.url("/");
|
||||||
Request cacheStoreRequest = new Request.Builder()
|
executeSynchronously("/", "Accept-Language", "fr-CA", "Accept-Charset", "UTF-8")
|
||||||
.url(url)
|
|
||||||
.addHeader("Accept-Language", "fr-CA")
|
|
||||||
.addHeader("Accept-Charset", "UTF-8")
|
|
||||||
.build();
|
|
||||||
executeSynchronously(cacheStoreRequest)
|
|
||||||
.assertCode(200)
|
.assertCode(200)
|
||||||
.assertBody("A");
|
.assertBody("A");
|
||||||
assertNull(server.takeRequest().getHeader("If-None-Match"));
|
assertNull(server.takeRequest().getHeader("If-None-Match"));
|
||||||
|
|
||||||
// Hit that stored response.
|
// Hit that stored response. It's different, but Vary says it doesn't matter.
|
||||||
Request cacheHitRequest = new Request.Builder()
|
RecordedResponse cacheHit = executeSynchronously(
|
||||||
.url(url)
|
"/", "Accept-Language", "en-US", "Accept-Charset", "UTF-8");
|
||||||
.addHeader("Accept-Language", "en-US") // Different, but Vary says it doesn't matter.
|
|
||||||
.addHeader("Accept-Charset", "UTF-8")
|
|
||||||
.build();
|
|
||||||
RecordedResponse cacheHit = executeSynchronously(cacheHitRequest);
|
|
||||||
|
|
||||||
// Check the merged response. The request is the application's original request.
|
// Check the merged response. The request is the application's original request.
|
||||||
cacheHit.assertCode(200)
|
cacheHit.assertCode(200)
|
||||||
.assertBody("A")
|
.assertBody("A")
|
||||||
.assertHeader("ETag", "v1")
|
.assertHeader("ETag", "v1")
|
||||||
.assertRequestUrl(cacheStoreRequest.url())
|
.assertRequestUrl(url)
|
||||||
.assertRequestHeader("Accept-Language", "en-US")
|
.assertRequestHeader("Accept-Language", "en-US")
|
||||||
.assertRequestHeader("Accept-Charset", "UTF-8");
|
.assertRequestHeader("Accept-Charset", "UTF-8");
|
||||||
|
|
||||||
@@ -1215,7 +1168,7 @@ public final class CallTest {
|
|||||||
.assertCode(200)
|
.assertCode(200)
|
||||||
.assertHeader("ETag", "v1")
|
.assertHeader("ETag", "v1")
|
||||||
.assertRequestMethod("GET")
|
.assertRequestMethod("GET")
|
||||||
.assertRequestUrl(cacheStoreRequest.url())
|
.assertRequestUrl(url)
|
||||||
.assertRequestHeader("Accept-Language")
|
.assertRequestHeader("Accept-Language")
|
||||||
.assertRequestHeader("Accept-Charset", "UTF-8");
|
.assertRequestHeader("Accept-Charset", "UTF-8");
|
||||||
|
|
||||||
@@ -1237,32 +1190,22 @@ public final class CallTest {
|
|||||||
.build();
|
.build();
|
||||||
|
|
||||||
// Store a response in the cache.
|
// Store a response in the cache.
|
||||||
HttpUrl url = server.url("/");
|
executeSynchronously("/", "Accept-Language", "fr-CA", "Accept-Charset", "UTF-8")
|
||||||
Request cacheStoreRequest = new Request.Builder()
|
|
||||||
.url(url)
|
|
||||||
.addHeader("Accept-Language", "fr-CA")
|
|
||||||
.addHeader("Accept-Charset", "UTF-8")
|
|
||||||
.build();
|
|
||||||
executeSynchronously(cacheStoreRequest)
|
|
||||||
.assertCode(200)
|
.assertCode(200)
|
||||||
.assertHeader("Donut", "a")
|
.assertHeader("Donut", "a")
|
||||||
.assertBody("A");
|
.assertBody("A");
|
||||||
assertNull(server.takeRequest().getHeader("If-None-Match"));
|
assertNull(server.takeRequest().getHeader("If-None-Match"));
|
||||||
|
|
||||||
// Hit that stored response.
|
// Hit that stored response. It's different, but Vary says it doesn't matter.
|
||||||
Request cacheHitRequest = new Request.Builder()
|
RecordedResponse cacheHit = executeSynchronously(
|
||||||
.url(url)
|
"/", "Accept-Language", "en-US", "Accept-Charset", "UTF-8");
|
||||||
.addHeader("Accept-Language", "en-US") // Different, but Vary says it doesn't matter.
|
|
||||||
.addHeader("Accept-Charset", "UTF-8")
|
|
||||||
.build();
|
|
||||||
RecordedResponse cacheHit = executeSynchronously(cacheHitRequest);
|
|
||||||
assertEquals("v1", server.takeRequest().getHeader("If-None-Match"));
|
assertEquals("v1", server.takeRequest().getHeader("If-None-Match"));
|
||||||
|
|
||||||
// Check the merged response. The request is the application's original request.
|
// Check the merged response. The request is the application's original request.
|
||||||
cacheHit.assertCode(200)
|
cacheHit.assertCode(200)
|
||||||
.assertBody("A")
|
.assertBody("A")
|
||||||
.assertHeader("Donut", "b")
|
.assertHeader("Donut", "b")
|
||||||
.assertRequestUrl(cacheStoreRequest.url())
|
.assertRequestUrl(server.url("/"))
|
||||||
.assertRequestHeader("Accept-Language", "en-US")
|
.assertRequestHeader("Accept-Language", "en-US")
|
||||||
.assertRequestHeader("Accept-Charset", "UTF-8")
|
.assertRequestHeader("Accept-Charset", "UTF-8")
|
||||||
.assertRequestHeader("If-None-Match"); // No If-None-Match on the user's request.
|
.assertRequestHeader("If-None-Match"); // No If-None-Match on the user's request.
|
||||||
@@ -1272,7 +1215,7 @@ public final class CallTest {
|
|||||||
.assertCode(200)
|
.assertCode(200)
|
||||||
.assertHeader("Donut", "a")
|
.assertHeader("Donut", "a")
|
||||||
.assertHeader("ETag", "v1")
|
.assertHeader("ETag", "v1")
|
||||||
.assertRequestUrl(cacheStoreRequest.url())
|
.assertRequestUrl(server.url("/"))
|
||||||
.assertRequestHeader("Accept-Language") // No Vary on Accept-Language.
|
.assertRequestHeader("Accept-Language") // No Vary on Accept-Language.
|
||||||
.assertRequestHeader("Accept-Charset", "UTF-8") // Because of Vary on Accept-Charset.
|
.assertRequestHeader("Accept-Charset", "UTF-8") // Because of Vary on Accept-Charset.
|
||||||
.assertRequestHeader("If-None-Match"); // This wasn't present in the original request.
|
.assertRequestHeader("If-None-Match"); // This wasn't present in the original request.
|
||||||
@@ -1325,43 +1268,35 @@ public final class CallTest {
|
|||||||
.cache(cache)
|
.cache(cache)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
Request cacheStoreRequest = new Request.Builder()
|
executeSynchronously("/", "Accept-Language", "fr-CA", "Accept-Charset", "UTF-8")
|
||||||
.url(server.url("/"))
|
|
||||||
.addHeader("Accept-Language", "fr-CA")
|
|
||||||
.addHeader("Accept-Charset", "UTF-8")
|
|
||||||
.build();
|
|
||||||
executeSynchronously(cacheStoreRequest)
|
|
||||||
.assertCode(200)
|
.assertCode(200)
|
||||||
.assertBody("A");
|
.assertBody("A");
|
||||||
assertNull(server.takeRequest().getHeader("If-None-Match"));
|
assertNull(server.takeRequest().getHeader("If-None-Match"));
|
||||||
|
|
||||||
Request cacheMissRequest = new Request.Builder()
|
// Different request, but Vary says it doesn't matter.
|
||||||
.url(server.url("/"))
|
RecordedResponse cacheHit = executeSynchronously(
|
||||||
.addHeader("Accept-Language", "en-US") // Different, but Vary says it doesn't matter.
|
"/", "Accept-Language", "en-US", "Accept-Charset", "UTF-8");
|
||||||
.addHeader("Accept-Charset", "UTF-8")
|
|
||||||
.build();
|
|
||||||
RecordedResponse cacheHit = executeSynchronously(cacheMissRequest);
|
|
||||||
assertEquals("v1", server.takeRequest().getHeader("If-None-Match"));
|
assertEquals("v1", server.takeRequest().getHeader("If-None-Match"));
|
||||||
|
|
||||||
// Check the user response. It has the application's original request.
|
// Check the user response. It has the application's original request.
|
||||||
cacheHit.assertCode(200)
|
cacheHit.assertCode(200)
|
||||||
.assertBody("B")
|
.assertBody("B")
|
||||||
.assertHeader("Donut", "b")
|
.assertHeader("Donut", "b")
|
||||||
.assertRequestUrl(cacheStoreRequest.url());
|
.assertRequestUrl(server.url("/"));
|
||||||
|
|
||||||
// Check the cache response. Even though it's a miss, we used the cache.
|
// Check the cache response. Even though it's a miss, we used the cache.
|
||||||
cacheHit.cacheResponse()
|
cacheHit.cacheResponse()
|
||||||
.assertCode(200)
|
.assertCode(200)
|
||||||
.assertHeader("Donut", "a")
|
.assertHeader("Donut", "a")
|
||||||
.assertHeader("ETag", "v1")
|
.assertHeader("ETag", "v1")
|
||||||
.assertRequestUrl(cacheStoreRequest.url());
|
.assertRequestUrl(server.url("/"));
|
||||||
|
|
||||||
// Check the network response. It has the network request, plus caching headers.
|
// Check the network response. It has the network request, plus caching headers.
|
||||||
cacheHit.networkResponse()
|
cacheHit.networkResponse()
|
||||||
.assertCode(200)
|
.assertCode(200)
|
||||||
.assertHeader("Donut", "b")
|
.assertHeader("Donut", "b")
|
||||||
.assertRequestHeader("If-None-Match", "v1") // If-None-Match in the validation request.
|
.assertRequestHeader("If-None-Match", "v1") // If-None-Match in the validation request.
|
||||||
.assertRequestUrl(cacheStoreRequest.url());
|
.assertRequestUrl(server.url("/"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test public void conditionalCacheMiss_Async() throws Exception {
|
@Test public void conditionalCacheMiss_Async() throws Exception {
|
||||||
@@ -1388,12 +1323,7 @@ public final class CallTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test public void onlyIfCachedReturns504WhenNotCached() throws Exception {
|
@Test public void onlyIfCachedReturns504WhenNotCached() throws Exception {
|
||||||
Request request = new Request.Builder()
|
executeSynchronously("/", "Cache-Control", "only-if-cached")
|
||||||
.url(server.url("/"))
|
|
||||||
.header("Cache-Control", "only-if-cached")
|
|
||||||
.build();
|
|
||||||
|
|
||||||
executeSynchronously(request)
|
|
||||||
.assertCode(504)
|
.assertCode(504)
|
||||||
.assertBody("")
|
.assertBody("")
|
||||||
.assertNoNetworkResponse()
|
.assertNoNetworkResponse()
|
||||||
@@ -1409,10 +1339,7 @@ public final class CallTest {
|
|||||||
server.enqueue(new MockResponse()
|
server.enqueue(new MockResponse()
|
||||||
.addHeader("ETag: v1")
|
.addHeader("ETag: v1")
|
||||||
.setBody("A"));
|
.setBody("A"));
|
||||||
Request cacheStoreRequest = new Request.Builder()
|
executeSynchronously("/")
|
||||||
.url(server.url("/"))
|
|
||||||
.build();
|
|
||||||
executeSynchronously(cacheStoreRequest)
|
|
||||||
.assertCode(200)
|
.assertCode(200)
|
||||||
.assertBody("A");
|
.assertBody("A");
|
||||||
|
|
||||||
@@ -1421,14 +1348,7 @@ public final class CallTest {
|
|||||||
client = client.newBuilder()
|
client = client.newBuilder()
|
||||||
.dns(new FakeDns().unknownHost())
|
.dns(new FakeDns().unknownHost())
|
||||||
.build();
|
.build();
|
||||||
Request conditionalGetRequest = new Request.Builder()
|
executeSynchronously("/").assertFailure(UnknownHostException.class);
|
||||||
.url(server.url("/"))
|
|
||||||
.build();
|
|
||||||
try {
|
|
||||||
executeSynchronously(conditionalGetRequest);
|
|
||||||
fail();
|
|
||||||
} catch (UnknownHostException expected) {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test public void redirect() throws Exception {
|
@Test public void redirect() throws Exception {
|
||||||
@@ -1444,7 +1364,7 @@ public final class CallTest {
|
|||||||
.setBody("/b has moved!"));
|
.setBody("/b has moved!"));
|
||||||
server.enqueue(new MockResponse().setBody("C"));
|
server.enqueue(new MockResponse().setBody("C"));
|
||||||
|
|
||||||
executeSynchronously(new Request.Builder().url(server.url("/a")).build())
|
executeSynchronously("/a")
|
||||||
.assertCode(200)
|
.assertCode(200)
|
||||||
.assertBody("C")
|
.assertBody("C")
|
||||||
.priorResponse()
|
.priorResponse()
|
||||||
@@ -1511,11 +1431,7 @@ public final class CallTest {
|
|||||||
.cookieJar(cookieJar)
|
.cookieJar(cookieJar)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
Request request = new Request.Builder()
|
executeSynchronously("/").assertCode(200);
|
||||||
.url(server.url("/"))
|
|
||||||
.build();
|
|
||||||
executeSynchronously(request)
|
|
||||||
.assertCode(200);
|
|
||||||
|
|
||||||
List<Cookie> responseCookies = cookieJar.takeResponseCookies();
|
List<Cookie> responseCookies = cookieJar.takeResponseCookies();
|
||||||
assertEquals(2, responseCookies.size());
|
assertEquals(2, responseCookies.size());
|
||||||
@@ -1537,11 +1453,7 @@ public final class CallTest {
|
|||||||
.cookieJar(cookieJar)
|
.cookieJar(cookieJar)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
Request request = new Request.Builder()
|
executeSynchronously("/").assertCode(200);
|
||||||
.url(server.url("/"))
|
|
||||||
.build();
|
|
||||||
executeSynchronously(request)
|
|
||||||
.assertCode(200);
|
|
||||||
|
|
||||||
RecordedRequest recordedRequest = server.takeRequest();
|
RecordedRequest recordedRequest = server.takeRequest();
|
||||||
assertEquals("a=b; c=d", recordedRequest.getHeader("Cookie"));
|
assertEquals("a=b; c=d", recordedRequest.getHeader("Cookie"));
|
||||||
@@ -1637,7 +1549,7 @@ public final class CallTest {
|
|||||||
}
|
}
|
||||||
server.enqueue(new MockResponse().setBody("Success!"));
|
server.enqueue(new MockResponse().setBody("Success!"));
|
||||||
|
|
||||||
executeSynchronously(new Request.Builder().url(server.url("/0")).build())
|
executeSynchronously("/0")
|
||||||
.assertCode(200)
|
.assertCode(200)
|
||||||
.assertBody("Success!");
|
.assertBody("Success!");
|
||||||
}
|
}
|
||||||
@@ -1692,12 +1604,8 @@ public final class CallTest {
|
|||||||
.setResponseCode(204)
|
.setResponseCode(204)
|
||||||
.setBody("I'm not even supposed to be here today."));
|
.setBody("I'm not even supposed to be here today."));
|
||||||
|
|
||||||
try {
|
executeSynchronously("/")
|
||||||
executeSynchronously(new Request.Builder().url(server.url("/")).build());
|
.assertFailure("HTTP 204 had non-zero Content-Length: 39");
|
||||||
fail();
|
|
||||||
} catch (ProtocolException e) {
|
|
||||||
assertEquals("HTTP 204 had non-zero Content-Length: 39", e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test public void http205WithBodyDisallowed() throws IOException {
|
@Test public void http205WithBodyDisallowed() throws IOException {
|
||||||
@@ -1705,12 +1613,8 @@ public final class CallTest {
|
|||||||
.setResponseCode(205)
|
.setResponseCode(205)
|
||||||
.setBody("I'm not even supposed to be here today."));
|
.setBody("I'm not even supposed to be here today."));
|
||||||
|
|
||||||
try {
|
executeSynchronously("/")
|
||||||
executeSynchronously(new Request.Builder().url(server.url("/")).build());
|
.assertFailure("HTTP 205 had non-zero Content-Length: 39");
|
||||||
fail();
|
|
||||||
} catch (ProtocolException e) {
|
|
||||||
assertEquals("HTTP 205 had non-zero Content-Length: 39", e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test public void canceledBeforeExecute() throws Exception {
|
@Test public void canceledBeforeExecute() throws Exception {
|
||||||
@@ -1998,13 +1902,9 @@ public final class CallTest {
|
|||||||
.setBody(gzippedBody)
|
.setBody(gzippedBody)
|
||||||
.addHeader("Content-Encoding: gzip"));
|
.addHeader("Content-Encoding: gzip"));
|
||||||
|
|
||||||
Request request = new Request.Builder()
|
|
||||||
.url(server.url("/"))
|
|
||||||
.build();
|
|
||||||
|
|
||||||
// Confirm that the user request doesn't have Accept-Encoding, and the user
|
// Confirm that the user request doesn't have Accept-Encoding, and the user
|
||||||
// response doesn't have a Content-Encoding or Content-Length.
|
// response doesn't have a Content-Encoding or Content-Length.
|
||||||
RecordedResponse userResponse = executeSynchronously(request);
|
RecordedResponse userResponse = executeSynchronously("/");
|
||||||
userResponse.assertCode(200)
|
userResponse.assertCode(200)
|
||||||
.assertRequestHeader("Accept-Encoding")
|
.assertRequestHeader("Accept-Encoding")
|
||||||
.assertHeader("Content-Encoding")
|
.assertHeader("Content-Encoding")
|
||||||
@@ -2029,11 +1929,7 @@ public final class CallTest {
|
|||||||
.authenticator(new RecordingOkAuthenticator("password"))
|
.authenticator(new RecordingOkAuthenticator("password"))
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
Request request = new Request.Builder()
|
executeSynchronously("/").assertBody("abcabcabc");
|
||||||
.url(server.url("/"))
|
|
||||||
.build();
|
|
||||||
executeSynchronously(request)
|
|
||||||
.assertBody("abcabcabc");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test public void asyncResponseCanBeConsumedLater() throws Exception {
|
@Test public void asyncResponseCanBeConsumedLater() throws Exception {
|
||||||
@@ -2065,7 +1961,7 @@ public final class CallTest {
|
|||||||
assertEquals("abc", response.body().string());
|
assertEquals("abc", response.body().string());
|
||||||
|
|
||||||
// Make another request just to confirm that that connection can be reused...
|
// Make another request just to confirm that that connection can be reused...
|
||||||
executeSynchronously(new Request.Builder().url(server.url("/")).build()).assertBody("def");
|
executeSynchronously("/").assertBody("def");
|
||||||
assertEquals(0, server.takeRequest().getSequenceNumber()); // New connection.
|
assertEquals(0, server.takeRequest().getSequenceNumber()); // New connection.
|
||||||
assertEquals(1, server.takeRequest().getSequenceNumber()); // Connection reused.
|
assertEquals(1, server.takeRequest().getSequenceNumber()); // Connection reused.
|
||||||
|
|
||||||
@@ -2076,7 +1972,7 @@ public final class CallTest {
|
|||||||
@Test public void userAgentIsIncludedByDefault() throws Exception {
|
@Test public void userAgentIsIncludedByDefault() throws Exception {
|
||||||
server.enqueue(new MockResponse());
|
server.enqueue(new MockResponse());
|
||||||
|
|
||||||
executeSynchronously(new Request.Builder().url(server.url("/")).build());
|
executeSynchronously("/");
|
||||||
|
|
||||||
RecordedRequest recordedRequest = server.takeRequest();
|
RecordedRequest recordedRequest = server.takeRequest();
|
||||||
assertTrue(recordedRequest.getHeader("User-Agent")
|
assertTrue(recordedRequest.getHeader("User-Agent")
|
||||||
@@ -2093,10 +1989,7 @@ public final class CallTest {
|
|||||||
client = client.newBuilder()
|
client = client.newBuilder()
|
||||||
.followRedirects(false)
|
.followRedirects(false)
|
||||||
.build();
|
.build();
|
||||||
RecordedResponse recordedResponse = executeSynchronously(
|
executeSynchronously("/a")
|
||||||
new Request.Builder().url(server.url("/a")).build());
|
|
||||||
|
|
||||||
recordedResponse
|
|
||||||
.assertBody("A")
|
.assertBody("A")
|
||||||
.assertCode(302);
|
.assertCode(302);
|
||||||
}
|
}
|
||||||
@@ -2141,11 +2034,7 @@ public final class CallTest {
|
|||||||
.build();
|
.build();
|
||||||
server.enqueue(new MockResponse().setHeaders(headers));
|
server.enqueue(new MockResponse().setHeaders(headers));
|
||||||
|
|
||||||
Request request = new Request.Builder()
|
executeSynchronously("/")
|
||||||
.url(server.url("/"))
|
|
||||||
.build();
|
|
||||||
|
|
||||||
executeSynchronously(request)
|
|
||||||
.assertHeader("a\tb", "c\u007fd")
|
.assertHeader("a\tb", "c\u007fd")
|
||||||
.assertHeader("\ud83c\udf69", "\u2615\ufe0f")
|
.assertHeader("\ud83c\udf69", "\u2615\ufe0f")
|
||||||
.assertHeader("", "ef");
|
.assertHeader("", "ef");
|
||||||
@@ -2322,10 +2211,143 @@ public final class CallTest {
|
|||||||
|
|
||||||
// Make an HTTP/2 request and confirm that the protocol matches.
|
// Make an HTTP/2 request and confirm that the protocol matches.
|
||||||
server.enqueue(new MockResponse());
|
server.enqueue(new MockResponse());
|
||||||
|
executeSynchronously("/");
|
||||||
|
assertEquals(Protocol.HTTP_2, protocolRef.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void serverSendsInvalidResponseHeaders() throws Exception {
|
||||||
|
server.enqueue(new MockResponse()
|
||||||
|
.setStatus("HTP/1.1 200 OK"));
|
||||||
|
|
||||||
|
executeSynchronously("/")
|
||||||
|
.assertFailure("Unexpected status line: HTP/1.1 200 OK");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void serverSendsInvalidCodeTooLarge() throws Exception {
|
||||||
|
server.enqueue(new MockResponse()
|
||||||
|
.setStatus("HTTP/1.1 2147483648 OK"));
|
||||||
|
|
||||||
|
executeSynchronously("/")
|
||||||
|
.assertFailure("Unexpected status line: HTTP/1.1 2147483648 OK");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void serverSendsInvalidCodeNotANumber() throws Exception {
|
||||||
|
server.enqueue(new MockResponse()
|
||||||
|
.setStatus("HTTP/1.1 00a OK"));
|
||||||
|
|
||||||
|
executeSynchronously("/")
|
||||||
|
.assertFailure("Unexpected status line: HTTP/1.1 00a OK");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void serverSendsUnnecessaryWhitespace() throws Exception {
|
||||||
|
server.enqueue(new MockResponse()
|
||||||
|
.setStatus(" HTTP/1.1 200 OK"));
|
||||||
|
|
||||||
|
executeSynchronously("/")
|
||||||
|
.assertFailure("Unexpected status line: HTTP/1.1 200 OK");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void connectFails() throws Exception {
|
||||||
|
server.shutdown();
|
||||||
|
|
||||||
|
executeSynchronously("/")
|
||||||
|
.assertFailure(IOException.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void requestBodySurvivesRetries() throws Exception {
|
||||||
|
server.enqueue(new MockResponse());
|
||||||
|
|
||||||
|
// Enable a misconfigured proxy selector to guarantee that the request is retried.
|
||||||
|
client = client.newBuilder()
|
||||||
|
.proxySelector(new FakeProxySelector()
|
||||||
|
.addProxy(server2.toProxyAddress()))
|
||||||
|
.build();
|
||||||
|
server2.shutdown();
|
||||||
|
|
||||||
|
Request request = new Request.Builder()
|
||||||
|
.url(server.url("/"))
|
||||||
|
.post(RequestBody.create(MediaType.parse("text/plain"), "abc"))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
executeSynchronously(request);
|
||||||
|
assertEquals("abc", server.takeRequest().getBody().readUtf8());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Ignore // This may fail in DNS lookup, which we don't have timeouts for.
|
||||||
|
@Test public void invalidHost() throws Exception {
|
||||||
|
Request request = new Request.Builder()
|
||||||
|
.url(HttpUrl.parse("http://1234.1.1.1/"))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
executeSynchronously(request)
|
||||||
|
.assertFailure(UnknownHostException.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void uploadBodySmallChunkedEncoding() throws Exception {
|
||||||
|
upload(true, 1048576, 256);
|
||||||
|
RecordedRequest recordedRequest = server.takeRequest();
|
||||||
|
assertEquals(1048576, recordedRequest.getBodySize());
|
||||||
|
assertFalse(recordedRequest.getChunkSizes().isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void uploadBodyLargeChunkedEncoding() throws Exception {
|
||||||
|
upload(true, 1048576, 65536);
|
||||||
|
RecordedRequest recordedRequest = server.takeRequest();
|
||||||
|
assertEquals(1048576, recordedRequest.getBodySize());
|
||||||
|
assertFalse(recordedRequest.getChunkSizes().isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void uploadBodySmallFixedLength() throws Exception {
|
||||||
|
upload(false, 1048576, 256);
|
||||||
|
RecordedRequest recordedRequest = server.takeRequest();
|
||||||
|
assertEquals(1048576, recordedRequest.getBodySize());
|
||||||
|
assertTrue(recordedRequest.getChunkSizes().isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void uploadBodyLargeFixedLength() throws Exception {
|
||||||
|
upload(false, 1048576, 65536);
|
||||||
|
RecordedRequest recordedRequest = server.takeRequest();
|
||||||
|
assertEquals(1048576, recordedRequest.getBodySize());
|
||||||
|
assertTrue(recordedRequest.getChunkSizes().isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void upload(
|
||||||
|
final boolean chunked, final int size, final int writeSize) throws Exception {
|
||||||
|
server.enqueue(new MockResponse());
|
||||||
executeSynchronously(new Request.Builder()
|
executeSynchronously(new Request.Builder()
|
||||||
.url(server.url("/"))
|
.url(server.url("/"))
|
||||||
|
.post(requestBody(chunked, size, writeSize))
|
||||||
.build());
|
.build());
|
||||||
assertEquals(Protocol.HTTP_2, protocolRef.get());
|
}
|
||||||
|
|
||||||
|
private RequestBody requestBody(final boolean chunked, final long size, final int writeSize) {
|
||||||
|
final byte[] buffer = new byte[writeSize];
|
||||||
|
Arrays.fill(buffer, (byte) 'x');
|
||||||
|
|
||||||
|
return new RequestBody() {
|
||||||
|
@Override public MediaType contentType() {
|
||||||
|
return MediaType.parse("text/plain; charset=utf-8");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public long contentLength() throws IOException {
|
||||||
|
return chunked ? -1L : size;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public void writeTo(BufferedSink sink) throws IOException {
|
||||||
|
for (int count = 0; count < size; count += writeSize) {
|
||||||
|
sink.write(buffer, 0, (int) Math.min(size - count, writeSize));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void emptyResponseBody() throws Exception {
|
||||||
|
server.enqueue(new MockResponse()
|
||||||
|
.addHeader("abc", "def"));
|
||||||
|
executeSynchronously("/")
|
||||||
|
.assertCode(200)
|
||||||
|
.assertHeader("abc", "def")
|
||||||
|
.assertBody("");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void makeFailingCall() {
|
private void makeFailingCall() {
|
||||||
@@ -2357,9 +2379,24 @@ public final class CallTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private RecordedResponse executeSynchronously(String path, String... headers) throws IOException {
|
||||||
|
Request.Builder builder = new Request.Builder();
|
||||||
|
builder.url(server.url(path));
|
||||||
|
for (int i = 0, size = headers.length; i < size; i += 2) {
|
||||||
|
builder.addHeader(headers[i], headers[i + 1]);
|
||||||
|
}
|
||||||
|
return executeSynchronously(builder.build());
|
||||||
|
}
|
||||||
|
|
||||||
private RecordedResponse executeSynchronously(Request request) throws IOException {
|
private RecordedResponse executeSynchronously(Request request) throws IOException {
|
||||||
Response response = client.newCall(request).execute();
|
Call call = client.newCall(request);
|
||||||
return new RecordedResponse(request, response, null, response.body().string(), null);
|
try {
|
||||||
|
Response response = call.execute();
|
||||||
|
String bodyString = response.body().string();
|
||||||
|
return new RecordedResponse(request, response, null, bodyString, null);
|
||||||
|
} catch (IOException e) {
|
||||||
|
return new RecordedResponse(request, null, null, null, e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -18,11 +18,12 @@ package okhttp3;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import javax.net.ssl.SSLContext;
|
import javax.net.ssl.SSLContext;
|
||||||
|
import javax.net.ssl.SSLException;
|
||||||
|
import javax.net.ssl.SSLSocketFactory;
|
||||||
import okhttp3.internal.SslContextBuilder;
|
import okhttp3.internal.SslContextBuilder;
|
||||||
import okhttp3.mockwebserver.MockResponse;
|
import okhttp3.mockwebserver.MockResponse;
|
||||||
import okhttp3.mockwebserver.MockWebServer;
|
import okhttp3.mockwebserver.MockWebServer;
|
||||||
import okhttp3.mockwebserver.SocketPolicy;
|
import okhttp3.mockwebserver.SocketPolicy;
|
||||||
import okhttp3.testing.RecordingHostnameVerifier;
|
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.rules.TestRule;
|
import org.junit.rules.TestRule;
|
||||||
@@ -30,6 +31,7 @@ import org.junit.rules.Timeout;
|
|||||||
|
|
||||||
import static okhttp3.TestUtil.defaultClient;
|
import static okhttp3.TestUtil.defaultClient;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
public final class ConnectionReuseTest {
|
public final class ConnectionReuseTest {
|
||||||
@Rule public final TestRule timeout = new Timeout(30_000);
|
@Rule public final TestRule timeout = new Timeout(30_000);
|
||||||
@@ -233,11 +235,71 @@ public final class ConnectionReuseTest {
|
|||||||
assertEquals(0, server.takeRequest().getSequenceNumber());
|
assertEquals(0, server.takeRequest().getSequenceNumber());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test public void connectionsAreNotReusedIfSslSocketFactoryChanges() throws Exception {
|
||||||
|
enableHttps();
|
||||||
|
server.enqueue(new MockResponse());
|
||||||
|
server.enqueue(new MockResponse());
|
||||||
|
|
||||||
|
Request request = new Request.Builder()
|
||||||
|
.url(server.url("/"))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
Response response = client.newCall(request).execute();
|
||||||
|
response.body().close();
|
||||||
|
|
||||||
|
// This client shares a connection pool but has a different SSL socket factory.
|
||||||
|
SSLContext sslContext2 = SSLContext.getInstance("TLS");
|
||||||
|
sslContext2.init(null, null, null);
|
||||||
|
SSLSocketFactory sslSocketFactory2 = sslContext2.getSocketFactory();
|
||||||
|
OkHttpClient anotherClient = client.newBuilder()
|
||||||
|
.sslSocketFactory(sslSocketFactory2)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// This client fails to connect because the new SSL socket factory refuses.
|
||||||
|
try {
|
||||||
|
anotherClient.newCall(request).execute();
|
||||||
|
fail();
|
||||||
|
} catch (SSLException expected) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void connectionsAreNotReusedIfHostnameVerifierChanges() throws Exception {
|
||||||
|
enableHttps();
|
||||||
|
server.enqueue(new MockResponse());
|
||||||
|
server.enqueue(new MockResponse());
|
||||||
|
|
||||||
|
Request request = new Request.Builder()
|
||||||
|
.url(server.url("/"))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
Response response1 = client.newCall(request).execute();
|
||||||
|
response1.body().close();
|
||||||
|
|
||||||
|
// This client shares a connection pool but has a different SSL socket factory.
|
||||||
|
OkHttpClient anotherClient = client.newBuilder()
|
||||||
|
.hostnameVerifier(new RecordingHostnameVerifier())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
Response response2 = anotherClient.newCall(request).execute();
|
||||||
|
response2.body().close();
|
||||||
|
|
||||||
|
assertEquals(0, server.takeRequest().getSequenceNumber());
|
||||||
|
assertEquals(0, server.takeRequest().getSequenceNumber());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void enableHttps() {
|
||||||
|
enableHttpsAndAlpn(Protocol.HTTP_1_1);
|
||||||
|
}
|
||||||
|
|
||||||
private void enableHttp2() {
|
private void enableHttp2() {
|
||||||
|
enableHttpsAndAlpn(Protocol.HTTP_2, Protocol.HTTP_1_1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void enableHttpsAndAlpn(Protocol... protocols) {
|
||||||
client = client.newBuilder()
|
client = client.newBuilder()
|
||||||
.sslSocketFactory(sslContext.getSocketFactory())
|
.sslSocketFactory(sslContext.getSocketFactory())
|
||||||
.hostnameVerifier(new RecordingHostnameVerifier())
|
.hostnameVerifier(new RecordingHostnameVerifier())
|
||||||
.protocols(Arrays.asList(Protocol.HTTP_2, Protocol.HTTP_1_1))
|
.protocols(Arrays.asList(protocols))
|
||||||
.build();
|
.build();
|
||||||
server.useHttps(sslContext.getSocketFactory(), false);
|
server.useHttps(sslContext.getSocketFactory(), false);
|
||||||
server.setProtocols(client.protocols());
|
server.setProtocols(client.protocols());
|
||||||
|
@@ -137,8 +137,14 @@ public final class RecordedResponse {
|
|||||||
return new RecordedResponse(cacheResponse.request(), cacheResponse, null, null, null);
|
return new RecordedResponse(cacheResponse.request(), cacheResponse, null, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void assertFailure(String... messages) {
|
public RecordedResponse assertFailure(Class<?> exceptionClass) {
|
||||||
|
assertTrue(exceptionClass.isInstance(failure));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RecordedResponse assertFailure(String... messages) {
|
||||||
assertNotNull(failure);
|
assertNotNull(failure);
|
||||||
assertTrue(failure.getMessage(), Arrays.asList(messages).contains(failure.getMessage()));
|
assertTrue(failure.getMessage(), Arrays.asList(messages).contains(failure.getMessage()));
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -13,7 +13,6 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package okhttp3;
|
package okhttp3;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -69,7 +68,6 @@ import okhttp3.mockwebserver.MockResponse;
|
|||||||
import okhttp3.mockwebserver.MockWebServer;
|
import okhttp3.mockwebserver.MockWebServer;
|
||||||
import okhttp3.mockwebserver.RecordedRequest;
|
import okhttp3.mockwebserver.RecordedRequest;
|
||||||
import okhttp3.mockwebserver.SocketPolicy;
|
import okhttp3.mockwebserver.SocketPolicy;
|
||||||
import okhttp3.testing.RecordingHostnameVerifier;
|
|
||||||
import okio.Buffer;
|
import okio.Buffer;
|
||||||
import okio.BufferedSink;
|
import okio.BufferedSink;
|
||||||
import okio.GzipSink;
|
import okio.GzipSink;
|
||||||
@@ -306,10 +304,9 @@ public final class URLConnectionTest {
|
|||||||
server.enqueue(new MockResponse().setBody("abc"));
|
server.enqueue(new MockResponse().setBody("abc"));
|
||||||
|
|
||||||
// Use a misconfigured proxy to guarantee that the request is retried.
|
// Use a misconfigured proxy to guarantee that the request is retried.
|
||||||
FakeProxySelector proxySelector = new FakeProxySelector();
|
|
||||||
proxySelector.proxies.add(server2.toProxyAddress());
|
|
||||||
urlFactory.setClient(urlFactory.client().newBuilder()
|
urlFactory.setClient(urlFactory.client().newBuilder()
|
||||||
.proxySelector(proxySelector)
|
.proxySelector(new FakeProxySelector()
|
||||||
|
.addProxy(server2.toProxyAddress()))
|
||||||
.build());
|
.build());
|
||||||
server2.shutdown();
|
server2.shutdown();
|
||||||
|
|
||||||
@@ -617,6 +614,8 @@ public final class URLConnectionTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(jwilson): tests below this marker need to be migrated to OkHttp's request/response API.
|
||||||
|
|
||||||
@Test public void connectViaHttpsWithSSLFallback() throws Exception {
|
@Test public void connectViaHttpsWithSSLFallback() throws Exception {
|
||||||
server.useHttps(sslContext.getSocketFactory(), false);
|
server.useHttps(sslContext.getSocketFactory(), false);
|
||||||
server.enqueue(new MockResponse().setSocketPolicy(FAIL_HANDSHAKE));
|
server.enqueue(new MockResponse().setSocketPolicy(FAIL_HANDSHAKE));
|
||||||
@@ -3560,19 +3559,6 @@ public final class URLConnectionTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class FakeProxySelector extends ProxySelector {
|
|
||||||
List<Proxy> proxies = new ArrayList<>();
|
|
||||||
|
|
||||||
@Override public List<Proxy> select(URI uri) {
|
|
||||||
// Don't handle 'socket' schemes, which the RI's Socket class may request (for SOCKS).
|
|
||||||
return uri.getScheme().equals("http") || uri.getScheme().equals("https") ? proxies
|
|
||||||
: Collections.singletonList(Proxy.NO_PROXY);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests that use this will fail unless boot classpath is set. Ex. {@code
|
* Tests that use this will fail unless boot classpath is set. Ex. {@code
|
||||||
* -Xbootclasspath/p:/tmp/alpn-boot-8.0.0.v20140317}
|
* -Xbootclasspath/p:/tmp/alpn-boot-8.0.0.v20140317}
|
||||||
|
@@ -44,7 +44,7 @@ import okhttp3.mockwebserver.MockResponse;
|
|||||||
import okhttp3.mockwebserver.MockWebServer;
|
import okhttp3.mockwebserver.MockWebServer;
|
||||||
import okhttp3.mockwebserver.RecordedRequest;
|
import okhttp3.mockwebserver.RecordedRequest;
|
||||||
import okhttp3.mockwebserver.SocketPolicy;
|
import okhttp3.mockwebserver.SocketPolicy;
|
||||||
import okhttp3.testing.RecordingHostnameVerifier;
|
import okhttp3.RecordingHostnameVerifier;
|
||||||
import okio.Buffer;
|
import okio.Buffer;
|
||||||
import okio.BufferedSink;
|
import okio.BufferedSink;
|
||||||
import okio.GzipSink;
|
import okio.GzipSink;
|
||||||
|
@@ -35,6 +35,7 @@ import javax.net.ssl.SSLSocketFactory;
|
|||||||
import okhttp3.Address;
|
import okhttp3.Address;
|
||||||
import okhttp3.Authenticator;
|
import okhttp3.Authenticator;
|
||||||
import okhttp3.ConnectionSpec;
|
import okhttp3.ConnectionSpec;
|
||||||
|
import okhttp3.FakeDns;
|
||||||
import okhttp3.Protocol;
|
import okhttp3.Protocol;
|
||||||
import okhttp3.Route;
|
import okhttp3.Route;
|
||||||
import okhttp3.internal.RouteDatabase;
|
import okhttp3.internal.RouteDatabase;
|
||||||
|
@@ -23,6 +23,7 @@ import java.security.cert.X509Certificate;
|
|||||||
import javax.net.ssl.HostnameVerifier;
|
import javax.net.ssl.HostnameVerifier;
|
||||||
import javax.net.ssl.SSLSession;
|
import javax.net.ssl.SSLSession;
|
||||||
import javax.security.auth.x500.X500Principal;
|
import javax.security.auth.x500.X500Principal;
|
||||||
|
import okhttp3.FakeSSLSession;
|
||||||
import okhttp3.internal.Util;
|
import okhttp3.internal.Util;
|
||||||
import org.junit.Ignore;
|
import org.junit.Ignore;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
@@ -30,7 +30,7 @@ import okhttp3.ResponseBody;
|
|||||||
import okhttp3.internal.SslContextBuilder;
|
import okhttp3.internal.SslContextBuilder;
|
||||||
import okhttp3.mockwebserver.MockResponse;
|
import okhttp3.mockwebserver.MockResponse;
|
||||||
import okhttp3.mockwebserver.MockWebServer;
|
import okhttp3.mockwebserver.MockWebServer;
|
||||||
import okhttp3.testing.RecordingHostnameVerifier;
|
import okhttp3.RecordingHostnameVerifier;
|
||||||
import okio.Buffer;
|
import okio.Buffer;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
|
Reference in New Issue
Block a user