Package io.netty.handler.codec.http2

Source Code of io.netty.handler.codec.http2.DelegatingHttp2HttpConnectionHandler

/*
* Copyright 2014 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License, version 2.0 (the
* "License"); you may not use this file except in compliance with the License. You may obtain a
* copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/

package io.netty.handler.codec.http2;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPromise;
import io.netty.channel.ChannelPromiseAggregator;
import io.netty.handler.codec.http.FullHttpMessage;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.HttpRequest;
import io.netty.handler.codec.http.HttpResponse;

import java.net.URI;
import java.util.Map;

/**
* Light weight wrapper around {@link DelegatingHttp2ConnectionHandler} to provide HTTP/1.x object to HTTP/2 encoding
*/
public class DelegatingHttp2HttpConnectionHandler extends DelegatingHttp2ConnectionHandler {

    public DelegatingHttp2HttpConnectionHandler(boolean server, Http2FrameListener listener) {
        super(server, listener);
    }

    public DelegatingHttp2HttpConnectionHandler(Http2Connection connection, Http2FrameReader frameReader,
                    Http2FrameWriter frameWriter, Http2InboundFlowController inboundFlow,
                    Http2OutboundFlowController outboundFlow, Http2FrameListener listener) {
        super(connection, frameReader, frameWriter, inboundFlow, outboundFlow, listener);
    }

    public DelegatingHttp2HttpConnectionHandler(Http2Connection connection, Http2FrameListener listener) {
        super(connection, listener);
    }

    /**
     * Add HTTP/2 headers based upon HTTP/1.x headers from a {@link HttpHeaders}
     *
     * @param httpHeaders The HTTP/1.x request object to pull headers from
     * @param http2Headers The HTTP/2 headers object to add headers to
     */
    private void addHeaders(HttpHeaders httpHeaders, DefaultHttp2Headers.Builder http2Headers) {
        String value = httpHeaders.get(HttpHeaders.Names.HOST);
        if (value != null) {
            URI hostUri = URI.create(value);
            // The authority MUST NOT include the deprecated "userinfo" subcomponent
            value = hostUri.getAuthority();
            if (value != null) {
                http2Headers.authority(value.replaceFirst("^.*@", ""));
            }
            value = hostUri.getScheme();
            if (value != null) {
                http2Headers.scheme(value);
            }
            httpHeaders.remove(HttpHeaders.Names.HOST);
        }

        // Consume the Authority extension header if present
        value = httpHeaders.get(HttpUtil.ExtensionHeaders.Names.AUTHORITY);
        if (value != null) {
            http2Headers.authority(value);
            httpHeaders.remove(HttpUtil.ExtensionHeaders.Names.AUTHORITY);
        }

        // Consume the Scheme extension header if present
        value = httpHeaders.get(HttpUtil.ExtensionHeaders.Names.SCHEME);
        if (value != null) {
            http2Headers.scheme(value);
            httpHeaders.remove(HttpUtil.ExtensionHeaders.Names.SCHEME);
        }
    }

    /**
     * Add HTTP/2 headers based upon HTTP/1.x headers from a {@link HttpRequest}
     *
     * @param httpRequest The HTTP/1.x request object to pull headers from
     * @param http2Headers The HTTP/2 headers object to add headers to
     */
    private void addRequestHeaders(HttpRequest httpRequest, DefaultHttp2Headers.Builder http2Headers) {
        http2Headers.path(httpRequest.uri());
        http2Headers.method(httpRequest.method().toString());
        addHeaders(httpRequest.headers(), http2Headers);
    }

    /**
     * Add HTTP/2 headers based upon HTTP/1.x headers from a {@link HttpRequest}
     *
     * @param httpResponse The HTTP/1.x response object to pull headers from
     * @param http2Headers The HTTP/2 headers object to add headers to
     */
    private void addResponseHeaders(HttpResponse httpResponse, DefaultHttp2Headers.Builder http2Headers) {
        http2Headers.status(Integer.toString(httpResponse.status().code()));
        addHeaders(httpResponse.headers(), http2Headers);
    }

    /**
     * Get the next stream id either from the {@link HttpHeaders} object or HTTP/2 codec
     *
     * @param httpHeaders The HTTP/1.x headers object to look for the stream id
     * @return The stream id to use with this {@link HttpHeaders} object
     * @throws Http2Exception If the {@code httpHeaders} object specifies an invalid stream id
     */
    private int getStreamId(HttpHeaders httpHeaders) throws Http2Exception {
        int streamId = 0;
        String value = httpHeaders.get(HttpUtil.ExtensionHeaders.Names.STREAM_ID);
        if (value == null) {
            streamId = nextStreamId();
        } else {
            try {
                streamId = Integer.parseInt(value);
            } catch (NumberFormatException e) {
                throw Http2Exception.format(Http2Error.INTERNAL_ERROR,
                                    "Invalid user-specified stream id value '%s'", value);
            }
            httpHeaders.remove(HttpUtil.ExtensionHeaders.Names.STREAM_ID);
        }

        return streamId;
    }

    /**
     * Handles conversion of a {@link FullHttpMessage} to HTTP/2 frames.
     */
    @Override
    @SuppressWarnings("deprecation")
    public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) {
        if (msg instanceof FullHttpMessage) {
            FullHttpMessage httpMsg = (FullHttpMessage) msg;
            boolean hasData = httpMsg.content().isReadable();

            // Convert and write the headers.
            HttpHeaders httpHeaders = httpMsg.headers();
            DefaultHttp2Headers.Builder http2Headers = DefaultHttp2Headers.newBuilder();
            if (msg instanceof HttpRequest) {
                addRequestHeaders((HttpRequest) msg, http2Headers);
            } else if (msg instanceof HttpResponse) {
                addResponseHeaders((HttpResponse) msg, http2Headers);
            }

            // Provide the user the opportunity to specify the streamId
            int streamId = 0;
            try {
                streamId = getStreamId(httpHeaders);
            } catch (Http2Exception e) {
                httpMsg.release();
                promise.setFailure(e);
                return;
            }

            // The Connection, Keep-Alive, Proxy-Connection, Transfer-Encoding,
            // and Upgrade headers are not valid and MUST not be sent.
            httpHeaders.remove(HttpHeaders.Names.CONNECTION);
            httpHeaders.remove(HttpHeaders.Names.KEEP_ALIVE);
            httpHeaders.remove(HttpHeaders.Names.PROXY_CONNECTION);
            httpHeaders.remove(HttpHeaders.Names.TRANSFER_ENCODING);

            // Add the HTTP headers which have not been consumed above
            for (Map.Entry<String, String> entry : httpHeaders.entries()) {
                http2Headers.add(entry.getKey(), entry.getValue());
            }

            if (hasData) {
                ChannelPromiseAggregator promiseAggregator = new ChannelPromiseAggregator(promise);
                ChannelPromise headerPromise = ctx.newPromise();
                ChannelPromise dataPromise = ctx.newPromise();
                promiseAggregator.add(headerPromise, dataPromise);
                writeHeaders(ctx, streamId, http2Headers.build(), 0, false, headerPromise);
                writeData(ctx, streamId, httpMsg.content(), 0, true, dataPromise);
            } else {
                writeHeaders(ctx, streamId, http2Headers.build(), 0, true, promise);
            }
        } else {
            ctx.write(msg, promise);
        }
    }
}
TOP

Related Classes of io.netty.handler.codec.http2.DelegatingHttp2HttpConnectionHandler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.