if (!logBody || !HttpEngine.hasBody(response)) { logger.log("<-- END HTTP"); } else if (bodyEncoded(response.headers())) {
/** * Cancels the request, if possible. Requests that are already complete * cannot be canceled. */ public void cancel() { canceled = true; if (engine != null) engine.cancel(); }
networkResponse = readNetworkResponse(); networkResponse = readNetworkResponse(); receiveHeaders(networkResponse.headers()); if (validate(cacheResponse, networkResponse)) { userResponse = cacheResponse.newBuilder() .request(userRequest) .priorResponse(stripBody(priorResponse)) .headers(combine(cacheResponse.headers(), networkResponse.headers())) .cacheResponse(stripBody(cacheResponse)) .networkResponse(stripBody(networkResponse)) .build(); networkResponse.body().close(); releaseStreamAllocation(); responseCache.update(cacheResponse, stripBody(userResponse)); userResponse = unzip(userResponse); return; } else { .priorResponse(stripBody(priorResponse)) .cacheResponse(stripBody(cacheResponse)) .networkResponse(stripBody(networkResponse)) .build(); if (hasBody(userResponse)) { maybeCache();
engine = new HttpEngine(client, request, false, false, forWebSocket, null, null, null); engine.releaseStreamAllocation(); throw new IOException("Canceled"); engine.sendRequest(); engine.readResponse(); releaseConnection = false; } catch (RequestException e) { HttpEngine retryEngine = engine.recover(e); if (retryEngine != null) { releaseConnection = false; HttpEngine retryEngine = engine.recover(e, null); if (retryEngine != null) { releaseConnection = false; StreamAllocation streamAllocation = engine.close(); streamAllocation.release(); Response response = engine.getResponse(); Request followUp = engine.followUpRequest(); engine.releaseStreamAllocation(); StreamAllocation streamAllocation = engine.close(); if (!engine.sameConnection(followUp.url())) {
if (httpStream != null) throw new IllegalStateException(); Request request = networkRequest(userRequest); httpStream = connect(); httpStream.setHttpEngine(this); if (callerWritesRequestBody && permitsRequestBody(networkRequest) && requestBodyOut == null) { long contentLength = OkHeaders.contentLength(request); if (bufferRequestBody) { .priorResponse(stripBody(priorResponse)) .cacheResponse(stripBody(cacheResponse)) .build(); } else { .priorResponse(stripBody(priorResponse)) .protocol(Protocol.HTTP_1_1) .code(504) userResponse = unzip(userResponse);
if (httpStream != null) throw new IllegalStateException(); Request request = networkRequest(userRequest); userResponse = new Response.Builder() .request(userRequest) .priorResponse(stripBody(priorResponse)) .protocol(Protocol.HTTP_1_1) .code(504) userResponse = cacheResponse.newBuilder() .request(userRequest) .priorResponse(stripBody(priorResponse)) .cacheResponse(stripBody(cacheResponse)) .build(); userResponse = unzip(userResponse); return; httpStream = connect(); httpStream.setHttpEngine(this); if (writeRequestHeadersEagerly()) { long contentLength = OkHeaders.contentLength(request); if (bufferRequestBody) {
/** * Report and attempt to recover from a failure to communicate with a server. Returns a new HTTP * engine that should be used for the retry if {@code e} is recoverable, or null if the failure is * permanent. Requests with a body can only be recovered if the body is buffered. */ public HttpEngine recover(IOException e, Sink requestBodyOut) { if (!streamAllocation.recover(e, requestBodyOut)) { return null; } if (!client.retryOnConnectionFailure()) { return null; } StreamAllocation streamAllocation = close(); // For failure recovery, use the same route selector with a new connection. return new HttpEngine(client, userRequest, bufferRequestBody, callerWritesRequestBody, forWebSocket, streamAllocation, (RetryableSink) requestBodyOut, priorResponse); }
/** * Prepares the HTTP headers and sends them to the server. * * <p>For streaming requests with a body, headers must be prepared <strong>before</strong> the * output stream has been written to. Otherwise the body would need to be buffered! * * <p>For non-streaming requests with a body, headers must be prepared <strong>after</strong> the * output stream has been written to and closed. This ensures that the {@code Content-Length} * header field receives the proper value. */ @Override public void writeRequestHeaders(Request request) throws IOException { httpEngine.writingRequestHeaders(); String requestLine = RequestLine.get( request, httpEngine.getConnection().route().proxy().type()); writeRequest(request.headers(), requestLine); }
/** * @param request the HTTP request without a body. The body must be written via the engine's * request body stream. * @param callerWritesRequestBody true for the {@code HttpURLConnection}-style interaction * model where control flow is returned to the calling application to write the request body * before the response body is readable. */ public HttpEngine(OkHttpClient client, Request request, boolean bufferRequestBody, boolean callerWritesRequestBody, boolean forWebSocket, StreamAllocation streamAllocation, RetryableSink requestBodyOut, Response priorResponse) { this.client = client; this.userRequest = request; this.bufferRequestBody = bufferRequestBody; this.callerWritesRequestBody = callerWritesRequestBody; this.forWebSocket = forWebSocket; this.streamAllocation = streamAllocation != null ? streamAllocation : new StreamAllocation(client.getConnectionPool(), createAddress(client, request)); this.requestBodyOut = requestBodyOut; this.priorResponse = priorResponse; }
networkResponse = readNetworkResponse(); } else if (!callerWritesRequestBody) { networkResponse = new NetworkInterceptorChain(0, networkRequest).proceed(networkRequest); networkResponse = readNetworkResponse(); receiveHeaders(networkResponse.headers()); if (validate(cacheResponse, networkResponse)) { userResponse = cacheResponse.newBuilder() .request(userRequest) .priorResponse(stripBody(priorResponse)) .headers(combine(cacheResponse.headers(), networkResponse.headers())) .cacheResponse(stripBody(cacheResponse)) .networkResponse(stripBody(networkResponse)) .build(); networkResponse.body().close(); releaseStreamAllocation(); responseCache.update(cacheResponse, stripBody(userResponse)); userResponse = unzip(userResponse); return; } else { .priorResponse(stripBody(priorResponse)) .cacheResponse(stripBody(cacheResponse)) .networkResponse(stripBody(networkResponse)) .build();
engine = new HttpEngine(client, request, false, false, forWebSocket, null, null, null); engine.releaseStreamAllocation(); throw new IOException("Canceled"); engine.sendRequest(); engine.readResponse(); releaseConnection = false; } catch (RequestException e) { HttpEngine retryEngine = engine.recover(e); if (retryEngine != null) { releaseConnection = false; HttpEngine retryEngine = engine.recover(e, null); if (retryEngine != null) { releaseConnection = false; StreamAllocation streamAllocation = engine.close(); streamAllocation.release(); Response response = engine.getResponse(); Request followUp = engine.followUpRequest(); engine.releaseStreamAllocation(); StreamAllocation streamAllocation = engine.close(); if (!engine.sameConnection(followUp.url())) {
if (httpStream != null) throw new IllegalStateException(); Request request = networkRequest(userRequest); httpStream = connect(); httpStream.setHttpEngine(this); if (callerWritesRequestBody && permitsRequestBody(networkRequest) && requestBodyOut == null) { long contentLength = OkHeaders.contentLength(request); if (bufferRequestBody) { .priorResponse(stripBody(priorResponse)) .cacheResponse(stripBody(cacheResponse)) .build(); } else { .priorResponse(stripBody(priorResponse)) .protocol(Protocol.HTTP_1_1) .code(504) userResponse = unzip(userResponse);
/** * Attempt to recover from failure to connect via a route. Returns a new HTTP engine * that should be used for the retry if there are other routes to try, or null if * there are no more routes to try. */ public HttpEngine recover(RouteException e) { if (!streamAllocation.recover(e)) { return null; } if (!client.getRetryOnConnectionFailure()) { return null; } StreamAllocation streamAllocation = close(); // For failure recovery, use the same route selector with a new connection. return new HttpEngine(client, userRequest, bufferRequestBody, callerWritesRequestBody, forWebSocket, streamAllocation, (RetryableSink) requestBodyOut, priorResponse); }
/** * Prepares the HTTP headers and sends them to the server. * * <p>For streaming requests with a body, headers must be prepared * <strong>before</strong> the output stream has been written to. Otherwise * the body would need to be buffered! * * <p>For non-streaming requests with a body, headers must be prepared * <strong>after</strong> the output stream has been written to and closed. * This ensures that the {@code Content-Length} header field receives the * proper value. */ @Override public void writeRequestHeaders(Request request) throws IOException { httpEngine.writingRequestHeaders(); String requestLine = RequestLine.get( request, httpEngine.getConnection().getRoute().proxy().type()); writeRequest(request.headers(), requestLine); }
/** * @param request the HTTP request without a body. The body must be written via the engine's * request body stream. * @param callerWritesRequestBody true for the {@code HttpURLConnection}-style interaction model * where control flow is returned to the calling application to write the request body before the * response body is readable. */ public HttpEngine(OkHttpClient client, Request request, boolean bufferRequestBody, boolean callerWritesRequestBody, boolean forWebSocket, StreamAllocation streamAllocation, RetryableSink requestBodyOut, Response priorResponse) { this.client = client; this.userRequest = request; this.bufferRequestBody = bufferRequestBody; this.callerWritesRequestBody = callerWritesRequestBody; this.forWebSocket = forWebSocket; this.streamAllocation = streamAllocation != null ? streamAllocation : new StreamAllocation(client.connectionPool(), createAddress(client, request)); this.requestBodyOut = requestBodyOut; this.priorResponse = priorResponse; }
networkResponse = readNetworkResponse(); networkResponse = readNetworkResponse(); receiveHeaders(networkResponse.headers()); if (validate(cacheResponse, networkResponse)) { userResponse = cacheResponse.newBuilder() .request(userRequest) .priorResponse(stripBody(priorResponse)) .headers(combine(cacheResponse.headers(), networkResponse.headers())) .cacheResponse(stripBody(cacheResponse)) .networkResponse(stripBody(networkResponse)) .build(); networkResponse.body().close(); releaseStreamAllocation(); responseCache.update(cacheResponse, stripBody(userResponse)); userResponse = unzip(userResponse); return; } else { .priorResponse(stripBody(priorResponse)) .cacheResponse(stripBody(cacheResponse)) .networkResponse(stripBody(networkResponse)) .build(); if (hasBody(userResponse)) { maybeCache();
engine = new HttpEngine(client, request, false, false, forWebSocket, null, null, null); engine.releaseStreamAllocation(); throw new IOException("Canceled"); engine.sendRequest(); engine.readResponse(); releaseConnection = false; } catch (RequestException e) { HttpEngine retryEngine = engine.recover(e.getLastConnectException(), null); if (retryEngine != null) { releaseConnection = false; HttpEngine retryEngine = engine.recover(e, null); if (retryEngine != null) { releaseConnection = false; StreamAllocation streamAllocation = engine.close(); streamAllocation.release(); Response response = engine.getResponse(); Request followUp = engine.followUpRequest(); engine.releaseStreamAllocation(); StreamAllocation streamAllocation = engine.close(); if (!engine.sameConnection(followUp.url())) {
public static String responseToString(final Response response) { ResponseBody responseBody = response.body(); if (HttpEngine.hasBody(response)) { BufferedSource source = responseBody.source(); try {
/** * Report and attempt to recover from a failure to communicate with a server. Returns a new * HTTP engine that should be used for the retry if {@code e} is recoverable, or null if * the failure is permanent. Requests with a body can only be recovered if the * body is buffered. */ public HttpEngine recover(IOException e, Sink requestBodyOut) { if (!streamAllocation.recover(e, requestBodyOut)) { return null; } if (!client.getRetryOnConnectionFailure()) { return null; } StreamAllocation streamAllocation = close(); // For failure recovery, use the same route selector with a new connection. return new HttpEngine(client, userRequest, bufferRequestBody, callerWritesRequestBody, forWebSocket, streamAllocation, (RetryableSink) requestBodyOut, priorResponse); }
/** * Prepares the HTTP headers and sends them to the server. * * <p>For streaming requests with a body, headers must be prepared * <strong>before</strong> the output stream has been written to. Otherwise * the body would need to be buffered! * * <p>For non-streaming requests with a body, headers must be prepared * <strong>after</strong> the output stream has been written to and closed. * This ensures that the {@code Content-Length} header field receives the * proper value. */ @Override public void writeRequestHeaders(Request request) throws IOException { httpEngine.writingRequestHeaders(); String requestLine = RequestLine.get( request, httpEngine.getConnection().getRoute().proxy().type()); writeRequest(request.headers(), requestLine); }