diff options
Diffstat (limited to 'okhttp')
5 files changed, 217 insertions, 119 deletions
diff --git a/okhttp/src/main/java/com/squareup/okhttp/Job.java b/okhttp/src/main/java/com/squareup/okhttp/Job.java index 64ce188..721acc8 100644 --- a/okhttp/src/main/java/com/squareup/okhttp/Job.java +++ b/okhttp/src/main/java/com/squareup/okhttp/Job.java @@ -117,7 +117,7 @@ final class Job extends NamedRunnable { } // Create the initial HTTP engine. Retries and redirects need new engine for each attempt. - engine = new HttpEngine(client, request, false, null, null, null); + engine = new HttpEngine(client, request, false, null, null, null, null); while (true) { if (canceled) return null; @@ -150,7 +150,7 @@ final class Job extends NamedRunnable { engine.releaseConnection(); return response.newBuilder() .body(new RealResponseBody(response, engine.getResponseBody())) - .redirectedBy(redirectedBy) + .priorResponse(redirectedBy) .build(); } @@ -159,9 +159,9 @@ final class Job extends NamedRunnable { } Connection connection = engine.close(); - redirectedBy = response.newBuilder().redirectedBy(redirectedBy).build(); // Chained. + redirectedBy = response.newBuilder().priorResponse(redirectedBy).build(); // Chained. request = redirect; - engine = new HttpEngine(client, request, false, connection, null, null); + engine = new HttpEngine(client, request, false, connection, null, null, null); } } diff --git a/okhttp/src/main/java/com/squareup/okhttp/Response.java b/okhttp/src/main/java/com/squareup/okhttp/Response.java index 13f9124..03c2d1f 100644 --- a/okhttp/src/main/java/com/squareup/okhttp/Response.java +++ b/okhttp/src/main/java/com/squareup/okhttp/Response.java @@ -49,7 +49,9 @@ public final class Response { private final Handshake handshake; private final Headers headers; private final Body body; - private final Response redirectedBy; + private Response networkResponse; + private Response cacheResponse; + private final Response priorResponse; private volatile ParsedHeaders parsedHeaders; // Lazily initialized. private volatile CacheControl cacheControl; // Lazily initialized. @@ -60,7 +62,9 @@ public final class Response { this.handshake = builder.handshake; this.headers = builder.headers.build(); this.body = builder.body; - this.redirectedBy = builder.redirectedBy; + this.networkResponse = builder.networkResponse; + this.cacheResponse = builder.cacheResponse; + this.priorResponse = builder.priorResponse; } /** @@ -134,8 +138,27 @@ public final class Response { * of the returned response should not be read because it has already been * consumed by the redirecting client. */ - public Response redirectedBy() { - return redirectedBy; + public Response priorResponse() { + return priorResponse; + } + + /** + * Returns the raw response received from the network. Will be null if this + * response didn't use the network, such as when the response is fully cached. + * The body of the returned response should not be read. + */ + public Response networkResponse() { + return networkResponse; + } + + /** + * Returns the raw response received from the cache. Will be null if this + * response didn't use the cache. For conditional get requests the cache + * response and network response may both be non-null. The body of the + * returned response should not be read. + */ + public Response cacheResponse() { + return cacheResponse; } // TODO: move out of public API @@ -361,7 +384,9 @@ public final class Response { private Handshake handshake; private Headers.Builder headers; private Body body; - private Response redirectedBy; + private Response networkResponse; + private Response cacheResponse; + private Response priorResponse; public Builder() { headers = new Headers.Builder(); @@ -373,7 +398,9 @@ public final class Response { this.handshake = response.handshake; this.headers = response.headers.newBuilder(); this.body = response.body; - this.redirectedBy = response.redirectedBy; + this.networkResponse = response.networkResponse; + this.cacheResponse = response.cacheResponse; + this.priorResponse = response.priorResponse; } public Builder request(Request request) { @@ -439,8 +466,32 @@ public final class Response { return header(OkHeaders.RESPONSE_SOURCE, responseSource + " " + statusLine.code()); } - public Builder redirectedBy(Response redirectedBy) { - this.redirectedBy = redirectedBy; + public Builder networkResponse(Response networkResponse) { + if (networkResponse != null) checkSupportResponse("networkResponse", networkResponse); + this.networkResponse = networkResponse; + return this; + } + + public Builder cacheResponse(Response cacheResponse) { + if (cacheResponse != null) checkSupportResponse("cacheResponse", cacheResponse); + this.cacheResponse = cacheResponse; + return this; + } + + private void checkSupportResponse(String name, Response response) { + if (response.body != null) { + throw new IllegalArgumentException(name + ".body != null"); + } else if (response.networkResponse != null) { + throw new IllegalArgumentException(name + ".networkResponse != null"); + } else if (response.cacheResponse != null) { + throw new IllegalArgumentException(name + ".cacheResponse != null"); + } else if (response.priorResponse != null) { + throw new IllegalArgumentException(name + ".priorResponse != null"); + } + } + + public Builder priorResponse(Response priorResponse) { + this.priorResponse = priorResponse; return this; } diff --git a/okhttp/src/main/java/com/squareup/okhttp/internal/http/CacheStrategy.java b/okhttp/src/main/java/com/squareup/okhttp/internal/http/CacheStrategy.java index 7cc7e21..75e13d9 100644 --- a/okhttp/src/main/java/com/squareup/okhttp/internal/http/CacheStrategy.java +++ b/okhttp/src/main/java/com/squareup/okhttp/internal/http/CacheStrategy.java @@ -46,14 +46,18 @@ public final class CacheStrategy { } } - public final Request request; - public final Response response; + /** The request to send on the network, or null if this call doesn't use the network. */ + public final Request networkRequest; + + /** The cached response to return or validate; or null if this call doesn't use a cache. */ + public final Response cacheResponse; + public final ResponseSource source; private CacheStrategy( - Request request, Response response, ResponseSource source) { - this.request = request; - this.response = response; + Request networkRequest, Response cacheResponse, ResponseSource source) { + this.networkRequest = networkRequest; + this.cacheResponse = cacheResponse; this.source = source; } @@ -167,12 +171,12 @@ public final class CacheStrategy { if (candidate.source != ResponseSource.CACHE && request.cacheControl().onlyIfCached()) { // We're forbidden from using the network, but the cache is insufficient. Response noneResponse = new Response.Builder() - .request(candidate.request) + .request(candidate.networkRequest) .statusLine(GATEWAY_TIMEOUT_STATUS_LINE) .setResponseSource(ResponseSource.NONE) .body(EMPTY_BODY) .build(); - return new CacheStrategy(candidate.request, noneResponse, ResponseSource.NONE); + return new CacheStrategy(null, noneResponse, ResponseSource.NONE); } return candidate; @@ -182,19 +186,19 @@ public final class CacheStrategy { private CacheStrategy getCandidate() { // No cached response. if (cacheResponse == null) { - return new CacheStrategy(request, cacheResponse, ResponseSource.NETWORK); + return new CacheStrategy(request, null, ResponseSource.NETWORK); } // Drop the cached response if it's missing a required handshake. if (request.isHttps() && cacheResponse.handshake() == null) { - return new CacheStrategy(request, cacheResponse, ResponseSource.NETWORK); + return new CacheStrategy(request, null, ResponseSource.NETWORK); } // If this response shouldn't have been stored, it should never be used // as a response source. This check should be redundant as long as the // persistence store is well-behaved and the rules are constant. if (!isCacheable(cacheResponse, request)) { - return new CacheStrategy(request, cacheResponse, ResponseSource.NETWORK); + return new CacheStrategy(request, null, ResponseSource.NETWORK); } CacheControl requestCaching = request.cacheControl(); @@ -230,7 +234,7 @@ public final class CacheStrategy { if (ageMillis > oneDayMillis && isFreshnessLifetimeHeuristic()) { builder.addHeader("Warning", "113 HttpURLConnection \"Heuristic expiration\""); } - return new CacheStrategy(request, builder.build(), ResponseSource.CACHE); + return new CacheStrategy(null, builder.build(), ResponseSource.CACHE); } Request.Builder conditionalRequestBuilder = request.newBuilder(); @@ -246,10 +250,9 @@ public final class CacheStrategy { } Request conditionalRequest = conditionalRequestBuilder.build(); - ResponseSource responseSource = hasConditions(conditionalRequest) - ? ResponseSource.CONDITIONAL_CACHE - : ResponseSource.NETWORK; - return new CacheStrategy(conditionalRequest, cacheResponse, responseSource); + return hasConditions(conditionalRequest) + ? new CacheStrategy(conditionalRequest, cacheResponse, ResponseSource.CONDITIONAL_CACHE) + : new CacheStrategy(conditionalRequest, null, ResponseSource.NETWORK); } /** diff --git a/okhttp/src/main/java/com/squareup/okhttp/internal/http/HttpEngine.java b/okhttp/src/main/java/com/squareup/okhttp/internal/http/HttpEngine.java index 38e26c3..f00fbe7 100644 --- a/okhttp/src/main/java/com/squareup/okhttp/internal/http/HttpEngine.java +++ b/okhttp/src/main/java/com/squareup/okhttp/internal/http/HttpEngine.java @@ -78,6 +78,7 @@ public class HttpEngine { private Connection connection; private RouteSelector routeSelector; private Route route; + private final Response priorResponse; private Transport transport; @@ -98,29 +99,51 @@ public class HttpEngine { */ public final boolean bufferRequestBody; - private Request originalRequest; - private Request request; + /** + * The original application-provided request. Never modified by OkHttp. When + * follow-up requests are necessary, they are derived from this request. + */ + private final Request userRequest; + + /** + * The request to send on the network, or null for no network request. This is + * derived from the user request, and customized to support OkHttp features + * like compression and caching. + */ + private Request networkRequest; + + /** + * The cached response, or null if the cache doesn't exist or cannot be used + * for this request. Conditional caching means this may be non-null even when + * the network request is non-null. Never modified by OkHttp. + */ + private Response cacheResponse; + + /** + * The response read from the network. Null if the network response hasn't + * been read yet, or if the network is not used. Never modified by OkHttp. + */ + private Response networkResponse; + + /** + * The user-visible response. This is derived from either the network + * response, cache response, or both. It is customized to support OkHttp + * features like compression and caching. + */ + private Response userResponse; + private Sink requestBodyOut; private BufferedSink bufferedRequestBody; private ResponseSource responseSource; /** Null until a response is received from the network or the cache. */ - private Response response; private Source responseTransferSource; private Source responseBody; private InputStream responseBodyBytes; - /** - * The cache response currently being validated on a conditional get. Null - * if the cached response doesn't exist or doesn't need validation. If the - * conditional get succeeds, these will be used for the response. If it fails, - * it will be set to null. - */ - private Response validatingResponse; - /** The cache request currently being populated from a network response. */ - private CacheRequest cacheRequest; + private CacheRequest storeRequest; /** * @param request the HTTP request without a body. The body must be @@ -134,14 +157,15 @@ public class HttpEngine { * recover from a failure. */ public HttpEngine(OkHttpClient client, Request request, boolean bufferRequestBody, - Connection connection, RouteSelector routeSelector, RetryableSink requestBodyOut) { + Connection connection, RouteSelector routeSelector, RetryableSink requestBodyOut, + Response priorResponse) { this.client = client; - this.originalRequest = request; - this.request = request; + this.userRequest = request; this.bufferRequestBody = bufferRequestBody; this.connection = connection; this.routeSelector = routeSelector; this.requestBodyOut = requestBodyOut; + this.priorResponse = priorResponse; if (connection != null) { connection.setOwner(this); @@ -160,33 +184,31 @@ public class HttpEngine { if (responseSource != null) return; // Already sent. if (transport != null) throw new IllegalStateException(); - prepareRawRequestHeaders(); - OkResponseCache responseCache = client.getOkResponseCache(); + Request request = networkRequest(userRequest); - Response cacheResponse = responseCache != null + OkResponseCache responseCache = client.getOkResponseCache(); + Response cacheCandidate = responseCache != null ? responseCache.get(request) : null; long now = System.currentTimeMillis(); - CacheStrategy cacheStrategy = new CacheStrategy.Factory(now, request, cacheResponse).get(); + CacheStrategy cacheStrategy = new CacheStrategy.Factory(now, request, cacheCandidate).get(); responseSource = cacheStrategy.source; - request = cacheStrategy.request; + networkRequest = cacheStrategy.networkRequest; + cacheResponse = cacheStrategy.cacheResponse; if (responseCache != null) { responseCache.trackResponse(responseSource); } - if (responseSource != ResponseSource.NETWORK) { - validatingResponse = cacheStrategy.response; - } - - if (cacheResponse != null && !responseSource.usesCache()) { - closeQuietly(cacheResponse.body()); // We don't need this cached response. Close it. + if (cacheCandidate != null + && (responseSource == ResponseSource.NONE || cacheResponse == null)) { + closeQuietly(cacheCandidate.body()); // The cache candidate wasn't applicable. Close it. } - if (responseSource.requiresConnection()) { + if (networkRequest != null) { // Open a connection unless we inherited one from a redirect. if (connection == null) { - connect(); + connect(networkRequest); } // Blow up if we aren't the current owner of the connection. @@ -208,21 +230,25 @@ public class HttpEngine { } // No need for the network! Promote the cached response immediately. - this.response = validatingResponse; - if (validatingResponse.body() != null) { - initContentStream(validatingResponse.body().source()); + this.userResponse = cacheResponse.newBuilder() + .request(userRequest) + .priorResponse(stripBody(priorResponse)) + .cacheResponse(stripBody(cacheResponse)) + .build(); + if (userResponse.body() != null) { + initContentStream(userResponse.body().source()); } } } - private Response cacheableResponse() { - // Use an unreadable response body when offering the response to the cache. - // The cache isn't allowed to consume the response body bytes! - return response.newBuilder().body(null).build(); + private static Response stripBody(Response response) { + return response != null && response.body() != null + ? response.newBuilder().body(null).build() + : response; } /** Connect to the origin server either directly or via a proxy. */ - private void connect() throws IOException { + private void connect(Request request) throws IOException { if (connection != null) throw new IllegalStateException(); if (routeSelector == null) { @@ -267,7 +293,7 @@ public class HttpEngine { } boolean hasRequestBody() { - return HttpMethod.hasRequestBody(request.method()); + return HttpMethod.hasRequestBody(userRequest.method()); } /** Returns the request body or null if this request doesn't have a body. */ @@ -286,26 +312,22 @@ public class HttpEngine { } public final boolean hasResponse() { - return response != null; - } - - public final ResponseSource responseSource() { - return responseSource; + return userResponse != null; } public final Request getRequest() { - return request; + return userRequest; } /** Returns the engine's response. */ // TODO: the returned body will always be null. public final Response getResponse() { - if (response == null) throw new IllegalStateException(); - return response; + if (userResponse == null) throw new IllegalStateException(); + return userResponse; } public final Source getResponseBody() { - if (response == null) throw new IllegalStateException(); + if (userResponse == null) throw new IllegalStateException(); return responseBody; } @@ -341,8 +363,8 @@ public class HttpEngine { Connection connection = close(); // For failure recovery, use the same route selector with a new connection. - return new HttpEngine(client, originalRequest, bufferRequestBody, connection, routeSelector, - (RetryableSink) requestBodyOut); + return new HttpEngine(client, userRequest, bufferRequestBody, connection, routeSelector, + (RetryableSink) requestBodyOut, priorResponse); } private boolean isRecoverable(IOException e) { @@ -367,13 +389,13 @@ public class HttpEngine { if (responseCache == null) return; // Should we cache this response for this request? - if (!CacheStrategy.isCacheable(response, request)) { - responseCache.maybeRemove(request); + if (!CacheStrategy.isCacheable(userResponse, networkRequest)) { + responseCache.maybeRemove(networkRequest); return; } // Offer this request to the cache. - cacheRequest = responseCache.put(cacheableResponse()); + storeRequest = responseCache.put(stripBody(userResponse)); } /** @@ -448,8 +470,8 @@ public class HttpEngine { */ private void initContentStream(Source transferSource) throws IOException { responseTransferSource = transferSource; - if (transparentGzip && "gzip".equalsIgnoreCase(response.header("Content-Encoding"))) { - response = response.newBuilder() + if (transparentGzip && "gzip".equalsIgnoreCase(userResponse.header("Content-Encoding"))) { + userResponse = userResponse.newBuilder() .removeHeader("Content-Encoding") .removeHeader("Content-Length") .build(); @@ -465,11 +487,11 @@ public class HttpEngine { */ public final boolean hasResponseBody() { // HEAD requests never yield a body regardless of the response headers. - if (request.method().equals("HEAD")) { + if (userRequest.method().equals("HEAD")) { return false; } - int responseCode = response.code(); + int responseCode = userResponse.code(); if ((responseCode < HTTP_CONTINUE || responseCode >= 200) && responseCode != HTTP_NO_CONTENT && responseCode != HTTP_NOT_MODIFIED) { @@ -479,8 +501,8 @@ public class HttpEngine { // If the Content-Length or Transfer-Encoding headers disagree with the // response code, the response is malformed. For best compatibility, we // honor the headers. - if (OkHeaders.contentLength(response) != -1 - || "chunked".equalsIgnoreCase(response.header("Transfer-Encoding"))) { + if (OkHeaders.contentLength(networkResponse) != -1 + || "chunked".equalsIgnoreCase(networkResponse.header("Transfer-Encoding"))) { return true; } @@ -493,7 +515,7 @@ public class HttpEngine { * <p>This client doesn't specify a default {@code Accept} header because it * doesn't know what content types the application is interested in. */ - private void prepareRawRequestHeaders() throws IOException { + private Request networkRequest(Request request) throws IOException { Request.Builder result = request.newBuilder(); if (request.getUserAgent() == null) { @@ -531,7 +553,7 @@ public class HttpEngine { OkHeaders.addCookies(result, cookies); } - request = result.build(); + return result.build(); } public static String getDefaultUserAgent() { @@ -550,9 +572,15 @@ public class HttpEngine { * headers and starts reading the HTTP response body if it exists. */ public final void readResponse() throws IOException { - if (response != null) return; - if (responseSource == null) throw new IllegalStateException("call sendRequest() first!"); - if (!responseSource.requiresConnection()) return; + if (userResponse != null) { + return; // Already ready. + } + if (networkRequest == null && cacheResponse == null) { + throw new IllegalStateException("call sendRequest() first!"); + } + if (networkRequest == null) { + return; // No network response to read. + } // Flush the request body if there's data outstanding. if (bufferedRequestBody != null && bufferedRequestBody.buffer().size() > 0) { @@ -560,14 +588,15 @@ public class HttpEngine { } if (sentRequestMillis == -1) { - if (OkHeaders.contentLength(request) == -1 && requestBodyOut instanceof RetryableSink) { + if (OkHeaders.contentLength(networkRequest) == -1 + && requestBodyOut instanceof RetryableSink) { // We might not learn the Content-Length until the request body has been buffered. long contentLength = ((RetryableSink) requestBodyOut).contentLength(); - request = request.newBuilder() + networkRequest = networkRequest.newBuilder() .header("Content-Length", Long.toString(contentLength)) .build(); } - transport.writeRequestHeaders(request); + transport.writeRequestHeaders(networkRequest); } if (requestBodyOut != null) { @@ -584,68 +613,79 @@ public class HttpEngine { transport.flushRequest(); - response = transport.readResponseHeaders() - .request(request) + networkResponse = transport.readResponseHeaders() + .request(networkRequest) .handshake(connection.getHandshake()) .header(OkHeaders.SENT_MILLIS, Long.toString(sentRequestMillis)) .header(OkHeaders.RECEIVED_MILLIS, Long.toString(System.currentTimeMillis())) .setResponseSource(responseSource) .build(); - connection.setHttpMinorVersion(response.httpMinorVersion()); - receiveHeaders(response.headers()); + connection.setHttpMinorVersion(networkResponse.httpMinorVersion()); + receiveHeaders(networkResponse.headers()); if (responseSource == ResponseSource.CONDITIONAL_CACHE) { - if (validatingResponse.validate(response)) { + if (cacheResponse.validate(networkResponse)) { + userResponse = cacheResponse.newBuilder() + .request(userRequest) + .priorResponse(stripBody(priorResponse)) + .headers(combine(cacheResponse.headers(), networkResponse.headers())) + .cacheResponse(stripBody(cacheResponse)) + .networkResponse(stripBody(networkResponse)) + .build(); transport.emptyTransferStream(); releaseConnection(); - response = combine(validatingResponse, response); // Update the cache after combining headers but before stripping the // Content-Encoding header (as performed by initContentStream()). OkResponseCache responseCache = client.getOkResponseCache(); responseCache.trackConditionalCacheHit(); - responseCache.update(validatingResponse, cacheableResponse()); - - if (validatingResponse.body() != null) { - initContentStream(validatingResponse.body().source()); + responseCache.update(cacheResponse, stripBody(userResponse)); + if (cacheResponse.body() != null) { + initContentStream(cacheResponse.body().source()); } + return; } else { - closeQuietly(validatingResponse.body()); + closeQuietly(cacheResponse.body()); } } + userResponse = networkResponse.newBuilder() + .request(userRequest) + .priorResponse(stripBody(priorResponse)) + .cacheResponse(stripBody(cacheResponse)) + .networkResponse(stripBody(networkResponse)) + .build(); + if (!hasResponseBody()) { // Don't call initContentStream() when the response doesn't have any content. - responseTransferSource = transport.getTransferStream(cacheRequest); + responseTransferSource = transport.getTransferStream(storeRequest); responseBody = responseTransferSource; return; } maybeCache(); - initContentStream(transport.getTransferStream(cacheRequest)); + initContentStream(transport.getTransferStream(storeRequest)); } /** * Combines cached headers with a network headers as defined by RFC 2616, * 13.5.3. */ - private static Response combine(Response cached, Response network) throws IOException { + private static Headers combine(Headers cachedHeaders, Headers networkHeaders) throws IOException { Headers.Builder result = new Headers.Builder(); - Headers cachedHeaders = cached.headers(); for (int i = 0; i < cachedHeaders.size(); i++) { String fieldName = cachedHeaders.name(i); String value = cachedHeaders.value(i); if ("Warning".equals(fieldName) && value.startsWith("1")) { continue; // drop 100-level freshness warnings } - if (!isEndToEnd(fieldName) || network.header(fieldName) == null) { + if (!isEndToEnd(fieldName) || networkHeaders.get(fieldName) == null) { result.add(fieldName, value); } } - Headers networkHeaders = network.headers(); for (int i = 0; i < networkHeaders.size(); i++) { String fieldName = networkHeaders.name(i); if (isEndToEnd(fieldName)) { @@ -653,7 +693,7 @@ public class HttpEngine { } } - return cached.newBuilder().headers(result.build()).build(); + return result.build(); } /** @@ -672,20 +712,20 @@ public class HttpEngine { } private TunnelRequest getTunnelConfig() { - if (!request.isHttps()) return null; + if (!userRequest.isHttps()) return null; - String userAgent = request.getUserAgent(); + String userAgent = userRequest.getUserAgent(); if (userAgent == null) userAgent = getDefaultUserAgent(); - URL url = request.url(); + URL url = userRequest.url(); return new TunnelRequest(url.getHost(), getEffectivePort(url), userAgent, - request.getProxyAuthorization()); + userRequest.getProxyAuthorization()); } public void receiveHeaders(Headers headers) throws IOException { CookieHandler cookieHandler = client.getCookieHandler(); if (cookieHandler != null) { - cookieHandler.put(request.uri(), OkHeaders.toMultimap(headers, null)); + cookieHandler.put(userRequest.uri(), OkHeaders.toMultimap(headers, null)); } } } diff --git a/okhttp/src/main/java/com/squareup/okhttp/internal/http/HttpURLConnectionImpl.java b/okhttp/src/main/java/com/squareup/okhttp/internal/http/HttpURLConnectionImpl.java index d43af99..899d914 100644 --- a/okhttp/src/main/java/com/squareup/okhttp/internal/http/HttpURLConnectionImpl.java +++ b/okhttp/src/main/java/com/squareup/okhttp/internal/http/HttpURLConnectionImpl.java @@ -267,7 +267,7 @@ public class HttpURLConnectionImpl extends HttpURLConnection { throw new ProtocolException(method + " does not support writing"); } } - httpEngine = newHttpEngine(method, null, null); + httpEngine = newHttpEngine(method, null, null, null); } catch (IOException e) { httpEngineFailure = e; throw e; @@ -275,7 +275,7 @@ public class HttpURLConnectionImpl extends HttpURLConnection { } private HttpEngine newHttpEngine(String method, Connection connection, - RetryableSink requestBody) { + RetryableSink requestBody, Response priorResponse) { Request.Builder builder = new Request.Builder() .url(getURL()) .method(method, null /* No body; that's passed separately. */); @@ -303,7 +303,8 @@ public class HttpURLConnectionImpl extends HttpURLConnection { engineClient = client.clone().setOkResponseCache(null); } - return new HttpEngine(engineClient, request, bufferRequestBody, connection, null, requestBody); + return new HttpEngine(engineClient, request, bufferRequestBody, connection, null, requestBody, + priorResponse); } /** @@ -323,6 +324,8 @@ public class HttpURLConnectionImpl extends HttpURLConnection { continue; } + Response response = httpEngine.getResponse(); + Retry retry = processResponseHeaders(); if (retry == Retry.NONE) { httpEngine.releaseConnection(); @@ -355,7 +358,8 @@ public class HttpURLConnectionImpl extends HttpURLConnection { } Connection connection = httpEngine.close(); - httpEngine = newHttpEngine(retryMethod, connection, (RetryableSink) requestBody); + httpEngine = newHttpEngine(retryMethod, connection, (RetryableSink) requestBody, + response); } } |
