use of okhttp3.Route in project okhttp by square.
the class URLConnectionTest method sslFallbackNotUsedWhenRecycledConnectionFails.
/**
* When a pooled connection fails, don't blame the route. Otherwise pooled connection failures can
* cause unnecessary SSL fallbacks.
*
* https://github.com/square/okhttp/issues/515
*/
@Test
public void sslFallbackNotUsedWhenRecycledConnectionFails() throws Exception {
server.useHttps(sslClient.socketFactory, false);
server.enqueue(new MockResponse().setBody("abc").setSocketPolicy(DISCONNECT_AT_END));
server.enqueue(new MockResponse().setBody("def"));
urlFactory.setClient(urlFactory.client().newBuilder().hostnameVerifier(new RecordingHostnameVerifier()).sslSocketFactory(suppressTlsFallbackClientSocketFactory(), sslClient.trustManager).build());
assertContent("abc", urlFactory.open(server.url("/").url()));
// Give the server time to disconnect.
Thread.sleep(500);
assertContent("def", urlFactory.open(server.url("/").url()));
Set<TlsVersion> tlsVersions = // v1.2 on OpenJDK 8.
EnumSet.of(TlsVersion.TLS_1_0, TlsVersion.TLS_1_2);
RecordedRequest request1 = server.takeRequest();
assertTrue(tlsVersions.contains(request1.getTlsVersion()));
RecordedRequest request2 = server.takeRequest();
assertTrue(tlsVersions.contains(request2.getTlsVersion()));
}
use of okhttp3.Route in project okhttp by square.
the class RealConnection method createTunnel.
/**
* To make an HTTPS connection over an HTTP proxy, send an unencrypted CONNECT request to create
* the proxy connection. This may need to be retried if the proxy requires authorization.
*/
private Request createTunnel(int readTimeout, int writeTimeout, Request tunnelRequest, HttpUrl url) throws IOException {
// Make an SSL Tunnel on the first message pair of each SSL + proxy connection.
String requestLine = "CONNECT " + Util.hostHeader(url, true) + " HTTP/1.1";
while (true) {
Http1Codec tunnelConnection = new Http1Codec(null, null, source, sink);
source.timeout().timeout(readTimeout, MILLISECONDS);
sink.timeout().timeout(writeTimeout, MILLISECONDS);
tunnelConnection.writeRequest(tunnelRequest.headers(), requestLine);
tunnelConnection.finishRequest();
Response response = tunnelConnection.readResponseHeaders(false).request(tunnelRequest).build();
// The response body from a CONNECT should be empty, but if it is not then we should consume
// it before proceeding.
long contentLength = HttpHeaders.contentLength(response);
if (contentLength == -1L) {
contentLength = 0L;
}
Source body = tunnelConnection.newFixedLengthSource(contentLength);
Util.skipAll(body, Integer.MAX_VALUE, TimeUnit.MILLISECONDS);
body.close();
switch(response.code()) {
case HTTP_OK:
// that it will almost certainly fail because the proxy has sent unexpected data.
if (!source.buffer().exhausted() || !sink.buffer().exhausted()) {
throw new IOException("TLS tunnel buffered too many bytes!");
}
return null;
case HTTP_PROXY_AUTH:
tunnelRequest = route.address().proxyAuthenticator().authenticate(route, response);
if (tunnelRequest == null)
throw new IOException("Failed to authenticate with proxy");
if ("close".equalsIgnoreCase(response.header("Connection"))) {
return tunnelRequest;
}
break;
default:
throw new IOException("Unexpected response code for CONNECT: " + response.code());
}
}
}
use of okhttp3.Route in project okhttp by square.
the class RouteSelector method next.
public Route next() throws IOException {
// Compute the next route to attempt.
if (!hasNextInetSocketAddress()) {
if (!hasNextProxy()) {
if (!hasNextPostponed()) {
throw new NoSuchElementException();
}
return nextPostponed();
}
lastProxy = nextProxy();
}
lastInetSocketAddress = nextInetSocketAddress();
Route route = new Route(address, lastProxy, lastInetSocketAddress);
if (routeDatabase.shouldPostpone(route)) {
postponedRoutes.add(route);
// We will only recurse in order to skip previously failed routes. They will be tried last.
return next();
}
return route;
}
use of okhttp3.Route in project okhttp by square.
the class StreamAllocation method streamFailed.
public void streamFailed(IOException e) {
Socket socket;
boolean noNewStreams = false;
synchronized (connectionPool) {
if (e instanceof StreamResetException) {
StreamResetException streamResetException = (StreamResetException) e;
if (streamResetException.errorCode == ErrorCode.REFUSED_STREAM) {
refusedStreamCount++;
}
// other errors must be retried on a new connection.
if (streamResetException.errorCode != ErrorCode.REFUSED_STREAM || refusedStreamCount > 1) {
noNewStreams = true;
route = null;
}
} else if (connection != null && (!connection.isMultiplexed() || e instanceof ConnectionShutdownException)) {
noNewStreams = true;
// If this route hasn't completed a call, avoid it for new connections.
if (connection.successCount == 0) {
if (route != null && e != null) {
routeSelector.connectFailed(route, e);
}
route = null;
}
}
socket = deallocate(noNewStreams, false, true);
}
closeQuietly(socket);
}
Aggregations