Search in sources :

Example 1 with RealInterceptorChain

use of okhttp3.internal.http.RealInterceptorChain in project okhttp by square.

the class CallServerInterceptor method intercept.

@Override
public Response intercept(Chain chain) throws IOException {
    HttpCodec httpCodec = ((RealInterceptorChain) chain).httpStream();
    StreamAllocation streamAllocation = ((RealInterceptorChain) chain).streamAllocation();
    Request request = chain.request();
    long sentRequestMillis = System.currentTimeMillis();
    httpCodec.writeRequestHeaders(request);
    Response.Builder responseBuilder = null;
    if (HttpMethod.permitsRequestBody(request.method()) && request.body() != null) {
        // we did get (such as a 4xx response) without ever transmitting the request body.
        if ("100-continue".equalsIgnoreCase(request.header("Expect"))) {
            httpCodec.flushRequest();
            responseBuilder = httpCodec.readResponseHeaders(true);
        }
        // Write the request body, unless an "Expect: 100-continue" expectation failed.
        if (responseBuilder == null) {
            Sink requestBodyOut = httpCodec.createRequestBody(request, request.body().contentLength());
            BufferedSink bufferedRequestBody = Okio.buffer(requestBodyOut);
            request.body().writeTo(bufferedRequestBody);
            bufferedRequestBody.close();
        }
    }
    httpCodec.finishRequest();
    if (responseBuilder == null) {
        responseBuilder = httpCodec.readResponseHeaders(false);
    }
    Response response = responseBuilder.request(request).handshake(streamAllocation.connection().handshake()).sentRequestAtMillis(sentRequestMillis).receivedResponseAtMillis(System.currentTimeMillis()).build();
    int code = response.code();
    if (forWebSocket && code == 101) {
        // Connection is upgrading, but we need to ensure interceptors see a non-null response body.
        response = response.newBuilder().body(Util.EMPTY_RESPONSE).build();
    } else {
        response = response.newBuilder().body(httpCodec.openResponseBody(response)).build();
    }
    if ("close".equalsIgnoreCase(response.request().header("Connection")) || "close".equalsIgnoreCase(response.header("Connection"))) {
        streamAllocation.noNewStreams();
    }
    if ((code == 204 || code == 205) && response.body().contentLength() > 0) {
        throw new ProtocolException("HTTP " + code + " had non-zero Content-Length: " + response.body().contentLength());
    }
    return response;
}
Also used : StreamAllocation(okhttp3.internal.connection.StreamAllocation) Response(okhttp3.Response) ProtocolException(java.net.ProtocolException) BufferedSink(okio.BufferedSink) Sink(okio.Sink) Request(okhttp3.Request) BufferedSink(okio.BufferedSink)

Example 2 with RealInterceptorChain

use of okhttp3.internal.http.RealInterceptorChain in project okhttp by square.

the class RetryAndFollowUpInterceptor method intercept.

@Override
public Response intercept(Chain chain) throws IOException {
    Request request = chain.request();
    streamAllocation = new StreamAllocation(client.connectionPool(), createAddress(request.url()), callStackTrace);
    int followUpCount = 0;
    Response priorResponse = null;
    while (true) {
        if (canceled) {
            streamAllocation.release();
            throw new IOException("Canceled");
        }
        Response response = null;
        boolean releaseConnection = true;
        try {
            response = ((RealInterceptorChain) chain).proceed(request, streamAllocation, null, null);
            releaseConnection = false;
        } catch (RouteException e) {
            // The attempt to connect via a route failed. The request will not have been sent.
            if (!recover(e.getLastConnectException(), false, request)) {
                throw e.getLastConnectException();
            }
            releaseConnection = false;
            continue;
        } catch (IOException e) {
            // An attempt to communicate with a server failed. The request may have been sent.
            boolean requestSendStarted = !(e instanceof ConnectionShutdownException);
            if (!recover(e, requestSendStarted, request))
                throw e;
            releaseConnection = false;
            continue;
        } finally {
            // We're throwing an unchecked exception. Release any resources.
            if (releaseConnection) {
                streamAllocation.streamFailed(null);
                streamAllocation.release();
            }
        }
        // Attach the prior response if it exists. Such responses never have a body.
        if (priorResponse != null) {
            response = response.newBuilder().priorResponse(priorResponse.newBuilder().body(null).build()).build();
        }
        Request followUp = followUpRequest(response);
        if (followUp == null) {
            if (!forWebSocket) {
                streamAllocation.release();
            }
            return response;
        }
        closeQuietly(response.body());
        if (++followUpCount > MAX_FOLLOW_UPS) {
            streamAllocation.release();
            throw new ProtocolException("Too many follow-up requests: " + followUpCount);
        }
        if (followUp.body() instanceof UnrepeatableRequestBody) {
            streamAllocation.release();
            throw new HttpRetryException("Cannot retry streamed HTTP body", response.code());
        }
        if (!sameConnection(response, followUp.url())) {
            streamAllocation.release();
            streamAllocation = new StreamAllocation(client.connectionPool(), createAddress(followUp.url()), callStackTrace);
        } else if (streamAllocation.codec() != null) {
            throw new IllegalStateException("Closing the body of " + response + " didn't close its backing stream. Bad interceptor?");
        }
        request = followUp;
        priorResponse = response;
    }
}
Also used : StreamAllocation(okhttp3.internal.connection.StreamAllocation) Response(okhttp3.Response) RouteException(okhttp3.internal.connection.RouteException) ProtocolException(java.net.ProtocolException) ConnectionShutdownException(okhttp3.internal.http2.ConnectionShutdownException) Request(okhttp3.Request) InterruptedIOException(java.io.InterruptedIOException) IOException(java.io.IOException) HttpRetryException(java.net.HttpRetryException)

Example 3 with RealInterceptorChain

use of okhttp3.internal.http.RealInterceptorChain in project okhttp by square.

the class ConnectInterceptor method intercept.

@Override
public Response intercept(Chain chain) throws IOException {
    RealInterceptorChain realChain = (RealInterceptorChain) chain;
    Request request = realChain.request();
    StreamAllocation streamAllocation = realChain.streamAllocation();
    // We need the network to satisfy this request. Possibly for validating a conditional GET.
    boolean doExtensiveHealthChecks = !request.method().equals("GET");
    HttpCodec httpCodec = streamAllocation.newStream(client, doExtensiveHealthChecks);
    RealConnection connection = streamAllocation.connection();
    return realChain.proceed(request, streamAllocation, httpCodec, connection);
}
Also used : HttpCodec(okhttp3.internal.http.HttpCodec) RealInterceptorChain(okhttp3.internal.http.RealInterceptorChain) Request(okhttp3.Request)

Example 4 with RealInterceptorChain

use of okhttp3.internal.http.RealInterceptorChain in project okhttp by square.

the class RealCall method getResponseWithInterceptorChain.

Response getResponseWithInterceptorChain() throws IOException {
    // Build a full stack of interceptors.
    List<Interceptor> interceptors = new ArrayList<>();
    interceptors.addAll(client.interceptors());
    interceptors.add(retryAndFollowUpInterceptor);
    interceptors.add(new BridgeInterceptor(client.cookieJar()));
    interceptors.add(new CacheInterceptor(client.internalCache()));
    interceptors.add(new ConnectInterceptor(client));
    if (!forWebSocket) {
        interceptors.addAll(client.networkInterceptors());
    }
    interceptors.add(new CallServerInterceptor(forWebSocket));
    Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, null, 0, originalRequest);
    return chain.proceed(originalRequest);
}
Also used : ConnectInterceptor(okhttp3.internal.connection.ConnectInterceptor) RealInterceptorChain(okhttp3.internal.http.RealInterceptorChain) ArrayList(java.util.ArrayList) CallServerInterceptor(okhttp3.internal.http.CallServerInterceptor) BridgeInterceptor(okhttp3.internal.http.BridgeInterceptor) CacheInterceptor(okhttp3.internal.cache.CacheInterceptor) ConnectInterceptor(okhttp3.internal.connection.ConnectInterceptor) RetryAndFollowUpInterceptor(okhttp3.internal.http.RetryAndFollowUpInterceptor) CallServerInterceptor(okhttp3.internal.http.CallServerInterceptor) BridgeInterceptor(okhttp3.internal.http.BridgeInterceptor) CacheInterceptor(okhttp3.internal.cache.CacheInterceptor)

Example 5 with RealInterceptorChain

use of okhttp3.internal.http.RealInterceptorChain in project okhttp by square.

the class RealInterceptorChain method proceed.

public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec, RealConnection connection) throws IOException {
    if (index >= interceptors.size())
        throw new AssertionError();
    calls++;
    // If we already have a stream, confirm that the incoming request will use it.
    if (this.httpCodec != null && !this.connection.supportsUrl(request.url())) {
        throw new IllegalStateException("network interceptor " + interceptors.get(index - 1) + " must retain the same host and port");
    }
    // If we already have a stream, confirm that this is the only call to chain.proceed().
    if (this.httpCodec != null && calls > 1) {
        throw new IllegalStateException("network interceptor " + interceptors.get(index - 1) + " must call proceed() exactly once");
    }
    // Call the next interceptor in the chain.
    RealInterceptorChain next = new RealInterceptorChain(interceptors, streamAllocation, httpCodec, connection, index + 1, request);
    Interceptor interceptor = interceptors.get(index);
    Response response = interceptor.intercept(next);
    // Confirm that the next interceptor made its required call to chain.proceed().
    if (httpCodec != null && index + 1 < interceptors.size() && next.calls != 1) {
        throw new IllegalStateException("network interceptor " + interceptor + " must call proceed() exactly once");
    }
    // Confirm that the intercepted response isn't null.
    if (response == null) {
        throw new NullPointerException("interceptor " + interceptor + " returned null");
    }
    return response;
}
Also used : Response(okhttp3.Response) Interceptor(okhttp3.Interceptor)

Aggregations

Request (okhttp3.Request)3 Response (okhttp3.Response)3 ProtocolException (java.net.ProtocolException)2 StreamAllocation (okhttp3.internal.connection.StreamAllocation)2 RealInterceptorChain (okhttp3.internal.http.RealInterceptorChain)2 IOException (java.io.IOException)1 InterruptedIOException (java.io.InterruptedIOException)1 HttpRetryException (java.net.HttpRetryException)1 ArrayList (java.util.ArrayList)1 Interceptor (okhttp3.Interceptor)1 CacheInterceptor (okhttp3.internal.cache.CacheInterceptor)1 ConnectInterceptor (okhttp3.internal.connection.ConnectInterceptor)1 RouteException (okhttp3.internal.connection.RouteException)1 BridgeInterceptor (okhttp3.internal.http.BridgeInterceptor)1 CallServerInterceptor (okhttp3.internal.http.CallServerInterceptor)1 HttpCodec (okhttp3.internal.http.HttpCodec)1 RetryAndFollowUpInterceptor (okhttp3.internal.http.RetryAndFollowUpInterceptor)1 ConnectionShutdownException (okhttp3.internal.http2.ConnectionShutdownException)1 BufferedSink (okio.BufferedSink)1 Sink (okio.Sink)1