Search in sources :

Example 1 with Http1Codec

use of okhttp3.internal.http1.Http1Codec in project okhttp by square.

the class RealConnection method createTunnel.

/**
   * To make an HTTPS connection over an HTTP proxy, send an unencrypted CONNECT request to create
   * the proxy connection. This may need to be retried if the proxy requires authorization.
   */
private Request createTunnel(int readTimeout, int writeTimeout, Request tunnelRequest, HttpUrl url) throws IOException {
    // Make an SSL Tunnel on the first message pair of each SSL + proxy connection.
    String requestLine = "CONNECT " + Util.hostHeader(url, true) + " HTTP/1.1";
    while (true) {
        Http1Codec tunnelConnection = new Http1Codec(null, null, source, sink);
        source.timeout().timeout(readTimeout, MILLISECONDS);
        sink.timeout().timeout(writeTimeout, MILLISECONDS);
        tunnelConnection.writeRequest(tunnelRequest.headers(), requestLine);
        tunnelConnection.finishRequest();
        Response response = tunnelConnection.readResponseHeaders(false).request(tunnelRequest).build();
        // The response body from a CONNECT should be empty, but if it is not then we should consume
        // it before proceeding.
        long contentLength = HttpHeaders.contentLength(response);
        if (contentLength == -1L) {
            contentLength = 0L;
        }
        Source body = tunnelConnection.newFixedLengthSource(contentLength);
        Util.skipAll(body, Integer.MAX_VALUE, TimeUnit.MILLISECONDS);
        body.close();
        switch(response.code()) {
            case HTTP_OK:
                // that it will almost certainly fail because the proxy has sent unexpected data.
                if (!source.buffer().exhausted() || !sink.buffer().exhausted()) {
                    throw new IOException("TLS tunnel buffered too many bytes!");
                }
                return null;
            case HTTP_PROXY_AUTH:
                tunnelRequest = route.address().proxyAuthenticator().authenticate(route, response);
                if (tunnelRequest == null)
                    throw new IOException("Failed to authenticate with proxy");
                if ("close".equalsIgnoreCase(response.header("Connection"))) {
                    return tunnelRequest;
                }
                break;
            default:
                throw new IOException("Unexpected response code for CONNECT: " + response.code());
        }
    }
}
Also used : Http1Codec(okhttp3.internal.http1.Http1Codec) Response(okhttp3.Response) IOException(java.io.IOException) BufferedSource(okio.BufferedSource) Source(okio.Source)

Aggregations

IOException (java.io.IOException)1 Response (okhttp3.Response)1 Http1Codec (okhttp3.internal.http1.Http1Codec)1 BufferedSource (okio.BufferedSource)1 Source (okio.Source)1