/** * @param requestHeaders the client's supplied request headers. This class * creates a private copy that it can mutate. * @param connection the connection used for an intermediate response * immediately prior to this request/response pair, such as a same-host * redirect. This engine assumes ownership of the connection and must * release it when it is unneeded. */ public HttpEngine(OkHttpClient client, Policy policy, String method, RawHeaders requestHeaders, Connection connection, RetryableOutputStream requestBodyOut) throws IOException { this.client = client; this.policy = policy; this.method = method; this.connection = connection; this.requestBodyOut = requestBodyOut; try { uri = Platform.get().toUriLenient(policy.getURL()); } catch (URISyntaxException e) { throw new IOException(e.getMessage()); } this.requestHeaders = new RequestHeaders(uri, new RawHeaders(requestHeaders)); }
/** * Discards the response body so that the connection can be reused. This * needs to be done judiciously, since it delays the current request in * order to speed up a potential future request that may never occur. * * <p>A stream may be discarded to encourage response caching (a response * cannot be cached unless it is consumed completely) or to enable connection * reuse. */ private static boolean discardStream(HttpEngine httpEngine, InputStream responseBodyIn) { Connection connection = httpEngine.connection; if (connection == null) return false; Socket socket = connection.getSocket(); if (socket == null) return false; try { int socketTimeout = socket.getSoTimeout(); socket.setSoTimeout(DISCARD_STREAM_TIMEOUT_MILLIS); try { Util.skipAll(responseBodyIn); return true; } finally { socket.setSoTimeout(socketTimeout); } } catch (IOException e) { return false; } }
public HttpEngine(OkHttpClient paramOkHttpClient, Request paramRequest, boolean paramBoolean1, boolean paramBoolean2, boolean paramBoolean3, Connection paramConnection, RouteSelector paramRouteSelector, RetryableSink paramRetryableSink, Response paramResponse) { this.client = paramOkHttpClient; this.userRequest = paramRequest; this.bufferRequestBody = paramBoolean1; this.callerWritesRequestBody = paramBoolean2; this.forWebSocket = paramBoolean3; this.connection = paramConnection; this.routeSelector = paramRouteSelector; this.requestBodyOut = null; this.priorResponse = paramResponse; if (paramConnection != null) { Internal.instance.setOwner(paramConnection, this); this.route = paramConnection.route; return; } this.route = null; }
/** * Discards the response body so that the connection can be reused. This * needs to be done judiciously, since it delays the current request in * order to speed up a potential future request that may never occur. * <p/> * <p>A stream may be discarded to encourage response caching (a response * cannot be cached unless it is consumed completely) or to enable connection * reuse. */ private static boolean discardStream(HttpEngine httpEngine, InputStream responseBodyIn) { Connection connection = httpEngine.connection; if (connection == null) return false; Socket socket = connection.getSocket(); if (socket == null) return false; try { int socketTimeout = socket.getSoTimeout(); socket.setSoTimeout(DISCARD_STREAM_TIMEOUT_MILLIS); try { Util.skipAll(responseBodyIn); return true; } finally { socket.setSoTimeout(socketTimeout); } } catch (IOException e) { return false; } }
private HttpEngine newHttpEngine(String method, RawHeaders requestHeaders, Connection connection, RetryableOutputStream requestBody) throws IOException { if (url.getProtocol().equals("http")) { return new HttpEngine(client, this, method, requestHeaders, connection, requestBody); } else if (url.getProtocol().equals("https")) { return new HttpsEngine(client, this, method, requestHeaders, connection, requestBody); } else { throw new AssertionError(); } }
/** * Returns the next route address to attempt. * * @throws NoSuchElementException if there are no more routes to attempt. */ public Connection next(String method) throws IOException { // Always prefer pooled connections over new connections. for (Connection pooled; (pooled = pool.get(address)) != null; ) { if (method.equals("GET") || pooled.isReadable()) return pooled; pooled.close(); } // Compute the next route to attempt. if (!hasNextTlsMode()) { if (!hasNextInetSocketAddress()) { if (!hasNextProxy()) { if (!hasNextPostponed()) { throw new NoSuchElementException(); } return new Connection(nextPostponed()); } lastProxy = nextProxy(); resetNextInetSocketAddress(lastProxy); } lastInetSocketAddress = nextInetSocketAddress(); resetNextTlsMode(); } boolean modernTls = nextTlsMode() == TLS_MODE_MODERN; Route route = new Route(address, lastProxy, lastInetSocketAddress, modernTls); 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(method); } return new Connection(route); }
/** * Clients should invoke this method when they encounter a connectivity * failure on a connection returned by this route selector. */ public void connectFailed(Connection connection, IOException failure) { Route failedRoute = connection.getRoute(); if (failedRoute.getProxy().type() != Proxy.Type.DIRECT && proxySelector != null) { // Tell the proxy selector when we fail to connect on a fresh connection. proxySelector.connectFailed(uri, failedRoute.getProxy().address(), failure); } routeDatabase.failed(failedRoute, failure); }