/** * Initialize the source for this response. It may be corrected later if the request headers * forbids network use. */ private void initResponseSource() throws IOException { responseSource = ResponseSource.NETWORK; if (!policy.getUseCaches()) return; OkResponseCache responseCache = client.getOkResponseCache(); if (responseCache == null) return; CacheResponse candidate = responseCache.get(uri, method, requestHeaders.getHeaders().toMultimap(false)); if (candidate == null) return; Map<String, List<String>> responseHeadersMap = candidate.getHeaders(); cachedResponseBody = candidate.getBody(); if (!acceptCacheResponseType(candidate) || responseHeadersMap == null || cachedResponseBody == null) { Util.closeQuietly(cachedResponseBody); return; } RawHeaders rawResponseHeaders = RawHeaders.fromMultimap(responseHeadersMap, true); cachedResponseHeaders = new ResponseHeaders(uri, rawResponseHeaders); long now = System.currentTimeMillis(); this.responseSource = cachedResponseHeaders.chooseResponseSource(now, requestHeaders); if (responseSource == ResponseSource.CACHE) { this.cacheResponse = candidate; setResponse(cachedResponseHeaders, cachedResponseBody); } else if (responseSource == ResponseSource.CONDITIONAL_CACHE) { this.cacheResponse = candidate; } else if (responseSource == ResponseSource.NETWORK) { Util.closeQuietly(cachedResponseBody); } else { throw new AssertionError(); } }
private Connection createNextConnection() { Object obj = client.getConnectionPool(); do { Connection connection1 = ((ConnectionPool) (obj)).get(address); if (connection1 == null) { break; } if (networkRequest.method().equals("GET") || Internal.instance.isReadable(connection1)) { return connection1; } Util.closeQuietly(connection1.getSocket()); } while (true); try { obj = new Connection(((ConnectionPool) (obj)), routeSelector.next()); } catch (IOException ioexception) { throw new RouteException(ioexception); } return ((Connection) (obj)); }
private static SSLContext sslContext(String keystoreFile, String password) throws GeneralSecurityException, IOException { KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType()); InputStream in = new FileInputStream(keystoreFile); try { keystore.load(in, password.toCharArray()); } finally { Util.closeQuietly(in); } KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); keyManagerFactory.init(keystore, password.toCharArray()); TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); trustManagerFactory.init(keystore); SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init( keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), new SecureRandom()); return sslContext; }
/** * Figures out what the response source will be, and opens a socket to that source if necessary. * Prepares the request headers and gets ready to start writing the request body if it exists. */ public final void sendRequest() throws IOException { if (responseSource != null) { return; } prepareRawRequestHeaders(); initResponseSource(); OkResponseCache responseCache = client.getOkResponseCache(); if (responseCache != null) { responseCache.trackResponse(responseSource); } // The raw response source may require the network, but the request // headers may forbid network use. In that case, dispose of the network // response and use a GATEWAY_TIMEOUT response instead, as specified // by http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.4. if (requestHeaders.isOnlyIfCached() && responseSource.requiresConnection()) { if (responseSource == ResponseSource.CONDITIONAL_CACHE) { Util.closeQuietly(cachedResponseBody); } this.responseSource = ResponseSource.CACHE; this.cacheResponse = GATEWAY_TIMEOUT_RESPONSE; RawHeaders rawResponseHeaders = RawHeaders.fromMultimap(cacheResponse.getHeaders(), true); setResponse(new ResponseHeaders(uri, rawResponseHeaders), cacheResponse.getBody()); } if (responseSource.requiresConnection()) { sendSocketRequest(); } else if (connection != null) { client.getConnectionPool().recycle(connection); connection = null; } }
/** * Releases this engine so that its resources may be either reused or closed. Also call {@link * #automaticallyReleaseConnectionToPool} unless the connection will be used to follow a redirect. */ public final void release(boolean streamCanceled) { // If the response body comes from the cache, close it. if (responseBodyIn == cachedResponseBody) { Util.closeQuietly(responseBodyIn); } if (!connectionReleased && connection != null) { connectionReleased = true; if (transport == null || !transport.makeReusable(streamCanceled, requestBodyOut, responseTransferIn)) { Util.closeQuietly(connection); connection = null; } else if (automaticallyReleaseConnectionToPool) { client.getConnectionPool().recycle(connection); connection = null; } } }
@Override public final void disconnect() { // Calling disconnect() before a connection exists should have no effect. if (httpEngine != null) { // We close the response body here instead of in // HttpEngine.release because that is called when input // has been completely read from the underlying socket. // However the response body can be a GZIPInputStream that // still has unread data. if (httpEngine.hasResponse()) { Util.closeQuietly(httpEngine.getResponseBody()); } httpEngine.release(true); } }
/** * Flushes the remaining request header and body, parses the HTTP response headers and starts * reading the HTTP response body if it exists. */ public final void readResponse() throws IOException { if (hasResponse()) { responseHeaders.setResponseSource(responseSource); return; } if (responseSource == null) { throw new IllegalStateException("readResponse() without sendRequest()"); } if (!responseSource.requiresConnection()) { return; } if (sentRequestMillis == -1) { if (requestBodyOut instanceof RetryableOutputStream) { int contentLength = ((RetryableOutputStream) requestBodyOut).contentLength(); requestHeaders.setContentLength(contentLength); } transport.writeRequestHeaders(); } if (requestBodyOut != null) { requestBodyOut.close(); if (requestBodyOut instanceof RetryableOutputStream) { transport.writeRequestBody((RetryableOutputStream) requestBodyOut); } } transport.flushRequest(); responseHeaders = transport.readResponseHeaders(); responseHeaders.setLocalTimestamps(sentRequestMillis, System.currentTimeMillis()); responseHeaders.setResponseSource(responseSource); if (responseSource == ResponseSource.CONDITIONAL_CACHE) { if (cachedResponseHeaders.validate(responseHeaders)) { release(false); ResponseHeaders combinedHeaders = cachedResponseHeaders.combine(responseHeaders); this.responseHeaders = combinedHeaders; // Update the cache after applying the combined headers but before initializing the content // stream, otherwise the Content-Encoding header (if present) will be stripped from the // combined headers and not end up in the cache file if transparent gzip compression is // turned on. OkResponseCache responseCache = client.getOkResponseCache(); responseCache.trackConditionalCacheHit(); responseCache.update(cacheResponse, policy.getHttpConnectionToCache()); initContentStream(cachedResponseBody); return; } else { Util.closeQuietly(cachedResponseBody); } } if (hasResponseBody()) { maybeCache(); // reentrant. this calls into user code which may call back into this! } initContentStream(transport.getTransferStream(cacheRequest)); }