All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.undefinedlabs.scope.deps.okhttp3.internal.http2.Http2Codec Maven / Gradle / Ivy

Go to download

Scope is a APM for tests to give engineering teams unprecedented visibility into their CI process to quickly identify, troubleshoot and fix failed builds. This artifact contains dependencies for Scope.

There is a newer version: 0.14.0-beta.2
Show newest version
package com.undefinedlabs.scope.deps.okhttp3.internal.http2;

import com.undefinedlabs.scope.deps.okhttp3.*;
import com.undefinedlabs.scope.deps.okhttp3.internal.Internal;
import com.undefinedlabs.scope.deps.okhttp3.internal.Util;
import com.undefinedlabs.scope.deps.okhttp3.internal.connection.StreamAllocation;
import com.undefinedlabs.scope.deps.okhttp3.internal.http.HttpCodec;
import com.undefinedlabs.scope.deps.okhttp3.internal.http.RealResponseBody;
import com.undefinedlabs.scope.deps.okhttp3.internal.http.RequestLine;
import com.undefinedlabs.scope.deps.okhttp3.internal.http.StatusLine;
import com.undefinedlabs.scope.deps.okio.*;

import java.io.IOException;
import java.net.ProtocolException;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.TimeUnit;

import static com.undefinedlabs.scope.deps.okhttp3.internal.http.StatusLine.HTTP_CONTINUE;
import static com.undefinedlabs.scope.deps.okhttp3.internal.http2.Header.*;

public final class Http2Codec implements HttpCodec {
    private static final ByteString CONNECTION = ByteString.encodeUtf8("connection");
    private static final ByteString HOST = ByteString.encodeUtf8("host");
    private static final ByteString KEEP_ALIVE = ByteString.encodeUtf8("keep-alive");
    private static final ByteString PROXY_CONNECTION = ByteString.encodeUtf8("proxy-connection");
    private static final ByteString TRANSFER_ENCODING = ByteString.encodeUtf8("transfer-encoding");
    private static final ByteString TE = ByteString.encodeUtf8("te");
    private static final ByteString ENCODING = ByteString.encodeUtf8("encoding");
    private static final ByteString UPGRADE = ByteString.encodeUtf8("upgrade");

    /** See http://tools.ietf.org/html/draft-ietf-httpbis-http2-09#section-8.1.3. */
    private static final List HTTP_2_SKIPPED_REQUEST_HEADERS = Util.immutableList(
            CONNECTION,
            HOST,
            KEEP_ALIVE,
            PROXY_CONNECTION,
            TE,
            TRANSFER_ENCODING,
            ENCODING,
            UPGRADE,
            TARGET_METHOD,
            TARGET_PATH,
            TARGET_SCHEME,
            TARGET_AUTHORITY);
    private static final List HTTP_2_SKIPPED_RESPONSE_HEADERS = Util.immutableList(
            CONNECTION,
            HOST,
            KEEP_ALIVE,
            PROXY_CONNECTION,
            TE,
            TRANSFER_ENCODING,
            ENCODING,
            UPGRADE);

    private final OkHttpClient client;
    final StreamAllocation streamAllocation;
    private final Http2Connection connection;
    private Http2Stream stream;

    public Http2Codec(
            OkHttpClient client, StreamAllocation streamAllocation, Http2Connection connection) {
        this.client = client;
        this.streamAllocation = streamAllocation;
        this.connection = connection;
    }

    @Override public Sink createRequestBody(Request request, long contentLength) {
        return stream.getSink();
    }

    @Override public void writeRequestHeaders(Request request) throws IOException {
        if (stream != null) return;

        boolean hasRequestBody = request.body() != null;
        List
requestHeaders = http2HeadersList(request); stream = connection.newStream(requestHeaders, hasRequestBody); stream.readTimeout().timeout(client.readTimeoutMillis(), TimeUnit.MILLISECONDS); stream.writeTimeout().timeout(client.writeTimeoutMillis(), TimeUnit.MILLISECONDS); } @Override public void flushRequest() throws IOException { connection.flush(); } @Override public void finishRequest() throws IOException { stream.getSink().close(); } @Override public Response.Builder readResponseHeaders(boolean expectContinue) throws IOException { List
headers = stream.takeResponseHeaders(); Response.Builder responseBuilder = readHttp2HeadersList(headers); if (expectContinue && Internal.instance.code(responseBuilder) == HTTP_CONTINUE) { return null; } return responseBuilder; } public static List
http2HeadersList(Request request) { Headers headers = request.headers(); List
result = new ArrayList<>(headers.size() + 4); result.add(new Header(TARGET_METHOD, request.method())); result.add(new Header(TARGET_PATH, RequestLine.requestPath(request.url()))); String host = request.header("Host"); if (host != null) { result.add(new Header(TARGET_AUTHORITY, host)); // Optional. } result.add(new Header(TARGET_SCHEME, request.url().scheme())); for (int i = 0, size = headers.size(); i < size; i++) { // header names must be lowercase. ByteString name = ByteString.encodeUtf8(headers.name(i).toLowerCase(Locale.US)); if (!HTTP_2_SKIPPED_REQUEST_HEADERS.contains(name)) { result.add(new Header(name, headers.value(i))); } } return result; } /** Returns headers for a name value block containing an HTTP/2 response. */ public static Response.Builder readHttp2HeadersList(List
headerBlock) throws IOException { StatusLine statusLine = null; Headers.Builder headersBuilder = new Headers.Builder(); for (int i = 0, size = headerBlock.size(); i < size; i++) { Header header = headerBlock.get(i); // If there were multiple header blocks they will be delimited by nulls. Discard existing // header blocks if the existing header block is a '100 Continue' intermediate response. if (header == null) { if (statusLine != null && statusLine.code == HTTP_CONTINUE) { statusLine = null; headersBuilder = new Headers.Builder(); } continue; } ByteString name = header.name; String value = header.value.utf8(); if (name.equals(RESPONSE_STATUS)) { statusLine = StatusLine.parse("HTTP/1.1 " + value); } else if (!HTTP_2_SKIPPED_RESPONSE_HEADERS.contains(name)) { Internal.instance.addLenient(headersBuilder, name.utf8(), value); } } if (statusLine == null) throw new ProtocolException("Expected ':status' header not present"); return new Response.Builder() .protocol(Protocol.HTTP_2) .code(statusLine.code) .message(statusLine.message) .headers(headersBuilder.build()); } @Override public ResponseBody openResponseBody(Response response) throws IOException { Source source = new StreamFinishingSource(stream.getSource()); return new RealResponseBody(response.headers(), Okio.buffer(source)); } @Override public void cancel() { if (stream != null) stream.closeLater(ErrorCode.CANCEL); } class StreamFinishingSource extends ForwardingSource { StreamFinishingSource(Source delegate) { super(delegate); } @Override public void close() throws IOException { streamAllocation.streamFinished(false, Http2Codec.this); super.close(); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy