1
0
mirror of https://github.com/square/okhttp.git synced 2025-11-24 18:41:06 +03:00

Confirm that call timeouts don't apply to SSE or web sockets.

This commit is contained in:
Jesse Wilson
2018-11-06 10:52:06 +11:00
parent af07e023f8
commit 04a74b2df4
11 changed files with 83 additions and 57 deletions

View File

@@ -18,6 +18,11 @@
<artifactId>okhttp</artifactId> <artifactId>okhttp</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
</dependency> </dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>okhttp-testing-support</artifactId>
<version>${project.version}</version>
</dependency>
<dependency> <dependency>
<groupId>com.google.code.findbugs</groupId> <groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId> <artifactId>jsr305</artifactId>

View File

@@ -47,6 +47,7 @@ public final class RealEventSource
.eventListener(EventListener.NONE) .eventListener(EventListener.NONE)
.build(); .build();
call = client.newCall(request); call = client.newCall(request);
call.timeout().clearTimeout();
call.enqueue(this); call.enqueue(this);
} }

View File

@@ -15,6 +15,7 @@
*/ */
package okhttp3.internal.sse; package okhttp3.internal.sse;
import java.util.concurrent.TimeUnit;
import okhttp3.OkHttpClient; import okhttp3.OkHttpClient;
import okhttp3.Request; import okhttp3.Request;
import okhttp3.mockwebserver.MockResponse; import okhttp3.mockwebserver.MockResponse;
@@ -25,13 +26,14 @@ import org.junit.After;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import static okhttp3.TestUtil.defaultClient;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
public final class EventSourceHttpTest { public final class EventSourceHttpTest {
@Rule public final MockWebServer server = new MockWebServer(); @Rule public final MockWebServer server = new MockWebServer();
private final EventSourceRecorder listener = new EventSourceRecorder(); private final EventSourceRecorder listener = new EventSourceRecorder();
private final EventSource.Factory factory = EventSources.createFactory(new OkHttpClient()); private OkHttpClient client = defaultClient();
@After public void after() { @After public void after() {
listener.assertExhausted(); listener.assertExhausted();
@@ -69,10 +71,30 @@ public final class EventSourceHttpTest {
listener.assertFailure(null); listener.assertFailure(null);
} }
@Test public void callTimeoutIsNotApplied() throws Exception {
client = client.newBuilder()
.callTimeout(100, TimeUnit.MILLISECONDS)
.build();
server.enqueue(new MockResponse()
.setBodyDelay(500, TimeUnit.MILLISECONDS)
.setHeader("content-type", "text/event-stream")
.setBody("data: hey\n\n"));
EventSource source = newEventSource();
assertEquals("/", source.request().url().encodedPath());
listener.assertOpen();
listener.assertEvent(null, null, "hey");
listener.assertClose();
}
private EventSource newEventSource() { private EventSource newEventSource() {
Request request = new Request.Builder() Request request = new Request.Builder()
.url(server.url("/")) .url(server.url("/"))
.build(); .build();
EventSource.Factory factory = EventSources.createFactory(client);
return factory.newEventSource(request, listener); return factory.newEventSource(request, listener);
} }
} }

View File

@@ -1,16 +1,44 @@
/*
* Copyright (C) 2018 Square, Inc.
*
* 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; package okhttp3;
import java.net.InetAddress;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections;
import java.util.List; import java.util.List;
import okhttp3.internal.SingleInetAddressDns;
import okhttp3.internal.http2.Header; import okhttp3.internal.http2.Header;
public final class TestUtil { public final class TestUtil {
public static final InetSocketAddress UNREACHABLE_ADDRESS public static final InetSocketAddress UNREACHABLE_ADDRESS
= new InetSocketAddress("198.51.100.1", 8080); = new InetSocketAddress("198.51.100.1", 8080);
/**
* A network that resolves only one IP address per host. Use this when testing route selection
* fallbacks to prevent the host machine's various IP addresses from interfering.
*/
private static final Dns SINGLE_INET_ADDRESS_DNS = new Dns() {
@Override public List<InetAddress> lookup(String hostname) throws UnknownHostException {
List<InetAddress> addresses = Dns.SYSTEM.lookup(hostname);
return Collections.singletonList(addresses.get(0));
}
};
private TestUtil() { private TestUtil() {
} }
@@ -30,7 +58,7 @@ public final class TestUtil {
return new OkHttpClient.Builder() return new OkHttpClient.Builder()
.connectionPool(connectionPool) .connectionPool(connectionPool)
.dispatcher(dispatcher) .dispatcher(dispatcher)
.dns(new SingleInetAddressDns()) // Prevent unexpected fallback addresses. .dns(SINGLE_INET_ADDRESS_DNS) // Prevent unexpected fallback addresses.
.build(); .build();
} }

View File

@@ -59,7 +59,6 @@ import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.SSLSocketFactory;
import okhttp3.internal.DoubleInetAddressDns; import okhttp3.internal.DoubleInetAddressDns;
import okhttp3.internal.RecordingOkAuthenticator; import okhttp3.internal.RecordingOkAuthenticator;
import okhttp3.internal.SingleInetAddressDns;
import okhttp3.internal.Util; import okhttp3.internal.Util;
import okhttp3.internal.Version; import okhttp3.internal.Version;
import okhttp3.internal.http.RecordingProxySelector; import okhttp3.internal.http.RecordingProxySelector;
@@ -1090,7 +1089,6 @@ public final class CallTest {
client = client.newBuilder() client = client.newBuilder()
.hostnameVerifier(new RecordingHostnameVerifier()) .hostnameVerifier(new RecordingHostnameVerifier())
.dns(new SingleInetAddressDns())
// Attempt RESTRICTED_TLS then fall back to MODERN_TLS. // Attempt RESTRICTED_TLS then fall back to MODERN_TLS.
.connectionSpecs(Arrays.asList(ConnectionSpec.RESTRICTED_TLS, ConnectionSpec.MODERN_TLS)) .connectionSpecs(Arrays.asList(ConnectionSpec.RESTRICTED_TLS, ConnectionSpec.MODERN_TLS))
.sslSocketFactory( .sslSocketFactory(
@@ -1119,7 +1117,6 @@ public final class CallTest {
// Attempt RESTRICTED_TLS then fall back to MODERN_TLS. // Attempt RESTRICTED_TLS then fall back to MODERN_TLS.
.connectionSpecs(Arrays.asList(ConnectionSpec.RESTRICTED_TLS, ConnectionSpec.MODERN_TLS)) .connectionSpecs(Arrays.asList(ConnectionSpec.RESTRICTED_TLS, ConnectionSpec.MODERN_TLS))
.hostnameVerifier(new RecordingHostnameVerifier()) .hostnameVerifier(new RecordingHostnameVerifier())
.dns(new SingleInetAddressDns())
.build(); .build();
Request request = new Request.Builder().url(server.url("/")).build(); Request request = new Request.Builder().url(server.url("/")).build();
@@ -1161,7 +1158,6 @@ public final class CallTest {
client = client.newBuilder() client = client.newBuilder()
.connectionSpecs(Arrays.asList(ConnectionSpec.MODERN_TLS, ConnectionSpec.CLEARTEXT)) .connectionSpecs(Arrays.asList(ConnectionSpec.MODERN_TLS, ConnectionSpec.CLEARTEXT))
.hostnameVerifier(new RecordingHostnameVerifier()) .hostnameVerifier(new RecordingHostnameVerifier())
.dns(new SingleInetAddressDns())
.sslSocketFactory( .sslSocketFactory(
suppressTlsFallbackClientSocketFactory(), handshakeCertificates.trustManager()) suppressTlsFallbackClientSocketFactory(), handshakeCertificates.trustManager())
.build(); .build();

View File

@@ -42,7 +42,6 @@ import okhttp3.RecordingEventListener.SecureConnectEnd;
import okhttp3.RecordingEventListener.SecureConnectStart; import okhttp3.RecordingEventListener.SecureConnectStart;
import okhttp3.internal.DoubleInetAddressDns; import okhttp3.internal.DoubleInetAddressDns;
import okhttp3.internal.RecordingOkAuthenticator; import okhttp3.internal.RecordingOkAuthenticator;
import okhttp3.internal.SingleInetAddressDns;
import okhttp3.logging.HttpLoggingInterceptor; import okhttp3.logging.HttpLoggingInterceptor;
import okhttp3.mockwebserver.MockResponse; import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer; import okhttp3.mockwebserver.MockWebServer;
@@ -80,7 +79,6 @@ public final class EventListenerTest {
public static final Matcher<Response> anyResponse = CoreMatchers.any(Response.class); public static final Matcher<Response> anyResponse = CoreMatchers.any(Response.class);
@Rule public final MockWebServer server = new MockWebServer(); @Rule public final MockWebServer server = new MockWebServer();
private final SingleInetAddressDns singleDns = new SingleInetAddressDns();
private final RecordingEventListener listener = new RecordingEventListener(); private final RecordingEventListener listener = new RecordingEventListener();
private final HandshakeCertificates handshakeCertificates = localhost(); private final HandshakeCertificates handshakeCertificates = localhost();
@@ -89,7 +87,6 @@ public final class EventListenerTest {
@Before public void setUp() { @Before public void setUp() {
client = defaultClient().newBuilder() client = defaultClient().newBuilder()
.dns(singleDns)
.eventListener(listener) .eventListener(listener)
.build(); .build();
@@ -437,8 +434,8 @@ public final class EventListenerTest {
server.enqueue(new MockResponse()); server.enqueue(new MockResponse());
FakeDns dns = new FakeDns(); FakeDns dns = new FakeDns();
dns.set("fakeurl", singleDns.lookup(server.getHostName())); dns.set("fakeurl", client.dns().lookup(server.getHostName()));
dns.set("www.fakeurl", singleDns.lookup(server.getHostName())); dns.set("www.fakeurl", client.dns().lookup(server.getHostName()));
client = client.newBuilder() client = client.newBuilder()
.dns(dns) .dns(dns)
@@ -513,7 +510,7 @@ public final class EventListenerTest {
assertEquals(200, response.code()); assertEquals(200, response.code());
response.body().close(); response.body().close();
InetAddress address = singleDns.lookup(server.getHostName()).get(0); InetAddress address = client.dns().lookup(server.getHostName()).get(0);
InetSocketAddress expectedAddress = new InetSocketAddress(address, server.getPort()); InetSocketAddress expectedAddress = new InetSocketAddress(address, server.getPort());
ConnectStart connectStart = listener.removeUpToEvent(ConnectStart.class); ConnectStart connectStart = listener.removeUpToEvent(ConnectStart.class);
@@ -541,7 +538,7 @@ public final class EventListenerTest {
} catch (IOException expected) { } catch (IOException expected) {
} }
InetAddress address = singleDns.lookup(server.getHostName()).get(0); InetAddress address = client.dns().lookup(server.getHostName()).get(0);
InetSocketAddress expectedAddress = new InetSocketAddress(address, server.getPort()); InetSocketAddress expectedAddress = new InetSocketAddress(address, server.getPort());
ConnectStart connectStart = listener.removeUpToEvent(ConnectStart.class); ConnectStart connectStart = listener.removeUpToEvent(ConnectStart.class);
@@ -593,7 +590,7 @@ public final class EventListenerTest {
assertEquals(200, response.code()); assertEquals(200, response.code());
response.body().close(); response.body().close();
InetAddress address = singleDns.lookup(server.getHostName()).get(0); InetAddress address = client.dns().lookup(server.getHostName()).get(0);
InetSocketAddress expectedAddress = new InetSocketAddress(address, server.getPort()); InetSocketAddress expectedAddress = new InetSocketAddress(address, server.getPort());
ConnectStart connectStart = listener.removeUpToEvent(ConnectStart.class); ConnectStart connectStart = listener.removeUpToEvent(ConnectStart.class);

View File

@@ -67,7 +67,6 @@ import okhttp3.internal.DoubleInetAddressDns;
import okhttp3.internal.Internal; import okhttp3.internal.Internal;
import okhttp3.internal.RecordingAuthenticator; import okhttp3.internal.RecordingAuthenticator;
import okhttp3.internal.RecordingOkAuthenticator; import okhttp3.internal.RecordingOkAuthenticator;
import okhttp3.internal.SingleInetAddressDns;
import okhttp3.internal.Util; import okhttp3.internal.Util;
import okhttp3.internal.Version; import okhttp3.internal.Version;
import okhttp3.internal.huc.OkHttpURLConnection; import okhttp3.internal.huc.OkHttpURLConnection;
@@ -88,7 +87,6 @@ import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.rules.TemporaryFolder; import org.junit.rules.TemporaryFolder;
import static java.util.Collections.singletonMap;
import static java.util.Locale.US; import static java.util.Locale.US;
import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.NANOSECONDS; import static java.util.concurrent.TimeUnit.NANOSECONDS;
@@ -719,7 +717,6 @@ public final class URLConnectionTest {
server.enqueue(new MockResponse().setSocketPolicy(FAIL_HANDSHAKE)); server.enqueue(new MockResponse().setSocketPolicy(FAIL_HANDSHAKE));
urlFactory.setClient(urlFactory.client().newBuilder() urlFactory.setClient(urlFactory.client().newBuilder()
.dns(new SingleInetAddressDns())
.connectionSpecs(Arrays.asList(ConnectionSpec.MODERN_TLS, ConnectionSpec.COMPATIBLE_TLS)) .connectionSpecs(Arrays.asList(ConnectionSpec.MODERN_TLS, ConnectionSpec.COMPATIBLE_TLS))
.hostnameVerifier(new RecordingHostnameVerifier()) .hostnameVerifier(new RecordingHostnameVerifier())
.sslSocketFactory( .sslSocketFactory(
@@ -1021,7 +1018,6 @@ public final class URLConnectionTest {
// Configure a single IP address for the host and a single configuration, so we only need one // Configure a single IP address for the host and a single configuration, so we only need one
// failure to fail permanently. // failure to fail permanently.
urlFactory.setClient(urlFactory.client().newBuilder() urlFactory.setClient(urlFactory.client().newBuilder()
.dns(new SingleInetAddressDns())
.sslSocketFactory( .sslSocketFactory(
handshakeCertificates.sslSocketFactory(), handshakeCertificates.trustManager()) handshakeCertificates.sslSocketFactory(), handshakeCertificates.trustManager())
.connectionSpecs(Util.immutableList(ConnectionSpec.MODERN_TLS)) .connectionSpecs(Util.immutableList(ConnectionSpec.MODERN_TLS))
@@ -2648,9 +2644,6 @@ public final class URLConnectionTest {
* https://code.google.com/p/android/issues/detail?id=41576 * https://code.google.com/p/android/issues/detail?id=41576
*/ */
@Test public void sameConnectionRedirectAndReuse() throws Exception { @Test public void sameConnectionRedirectAndReuse() throws Exception {
urlFactory.setClient(urlFactory.client().newBuilder()
.dns(new SingleInetAddressDns())
.build());
server.enqueue(new MockResponse() server.enqueue(new MockResponse()
.setResponseCode(HttpURLConnection.HTTP_MOVED_TEMP) .setResponseCode(HttpURLConnection.HTTP_MOVED_TEMP)
.setSocketPolicy(SHUTDOWN_INPUT_AT_END) .setSocketPolicy(SHUTDOWN_INPUT_AT_END)

View File

@@ -1,33 +0,0 @@
/*
* Copyright (C) 2014 Square, Inc.
*
* 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.internal;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Collections;
import java.util.List;
import okhttp3.Dns;
/**
* A network that resolves only one IP address per host. Use this when testing route selection
* fallbacks to prevent the host machine's various IP addresses from interfering.
*/
public class SingleInetAddressDns implements Dns {
@Override public List<InetAddress> lookup(String hostname) throws UnknownHostException {
List<InetAddress> addresses = Dns.SYSTEM.lookup(hostname);
return Collections.singletonList(addresses.get(0));
}
}

View File

@@ -51,7 +51,6 @@ import okhttp3.TestLogHandler;
import okhttp3.TestUtil; import okhttp3.TestUtil;
import okhttp3.internal.DoubleInetAddressDns; import okhttp3.internal.DoubleInetAddressDns;
import okhttp3.internal.RecordingOkAuthenticator; import okhttp3.internal.RecordingOkAuthenticator;
import okhttp3.internal.SingleInetAddressDns;
import okhttp3.internal.Util; import okhttp3.internal.Util;
import okhttp3.internal.connection.RealConnection; import okhttp3.internal.connection.RealConnection;
import okhttp3.mockwebserver.Dispatcher; import okhttp3.mockwebserver.Dispatcher;
@@ -125,7 +124,6 @@ public final class HttpOverHttp2Test {
private static OkHttpClient buildHttp2Client() { private static OkHttpClient buildHttp2Client() {
return defaultClient().newBuilder() return defaultClient().newBuilder()
.protocols(Arrays.asList(Protocol.HTTP_2, Protocol.HTTP_1_1)) .protocols(Arrays.asList(Protocol.HTTP_2, Protocol.HTTP_1_1))
.dns(new SingleInetAddressDns())
.sslSocketFactory( .sslSocketFactory(
handshakeCertificates.sslSocketFactory(), handshakeCertificates.trustManager()) handshakeCertificates.sslSocketFactory(), handshakeCertificates.trustManager())
.hostnameVerifier(new RecordingHostnameVerifier()) .hostnameVerifier(new RecordingHostnameVerifier())

View File

@@ -677,6 +677,24 @@ public final class WebSocketHttpTest {
assertEquals(Collections.emptyList(), listener.recordedEventTypes()); assertEquals(Collections.emptyList(), listener.recordedEventTypes());
} }
@Test public void callTimeoutIsNotApplied() throws Exception {
client = client.newBuilder()
.callTimeout(100, TimeUnit.MILLISECONDS)
.build();
webServer.enqueue(new MockResponse()
.withWebSocketUpgrade(serverListener));
newWebSocket();
clientListener.assertOpen();
WebSocket server = serverListener.assertOpen();
Thread.sleep(500);
server.send("Hello, WebSockets!");
clientListener.assertTextMessage("Hello, WebSockets!");
}
private MockResponse upgradeResponse(RecordedRequest request) { private MockResponse upgradeResponse(RecordedRequest request) {
String key = request.getHeader("Sec-WebSocket-Key"); String key = request.getHeader("Sec-WebSocket-Key");
return new MockResponse() return new MockResponse()

View File

@@ -189,6 +189,7 @@ public final class RealWebSocket implements WebSocket, WebSocketReader.FrameCall
.header("Sec-WebSocket-Version", "13") .header("Sec-WebSocket-Version", "13")
.build(); .build();
call = Internal.instance.newWebSocketCall(client, request); call = Internal.instance.newWebSocketCall(client, request);
call.timeout().clearTimeout();
call.enqueue(new Callback() { call.enqueue(new Callback() {
@Override public void onResponse(Call call, Response response) { @Override public void onResponse(Call call, Response response) {
try { try {