Search in sources :

Example 56 with Http2Exception

use of io.netty.handler.codec.http2.Http2Exception in project netty by netty.

the class InboundHttp2ToHttpAdapterTest method clientRequestSingleHeaderCookieSplitIntoMultipleEntries.

@Test
public void clientRequestSingleHeaderCookieSplitIntoMultipleEntries() throws Exception {
    boostrapEnv(1, 1, 1);
    final FullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "/some/path/resource2", true);
    try {
        HttpHeaders httpHeaders = request.headers();
        httpHeaders.set(HttpConversionUtil.ExtensionHeaderNames.SCHEME.text(), "https");
        httpHeaders.set(HttpHeaderNames.HOST, "example.org");
        httpHeaders.setInt(HttpConversionUtil.ExtensionHeaderNames.STREAM_ID.text(), 3);
        httpHeaders.setInt(HttpHeaderNames.CONTENT_LENGTH, 0);
        httpHeaders.set(HttpHeaderNames.COOKIE, "a=b; c=d; e=f");
        httpHeaders.setShort(HttpConversionUtil.ExtensionHeaderNames.STREAM_WEIGHT.text(), (short) 16);
        final Http2Headers http2Headers = new DefaultHttp2Headers().method(new AsciiString("GET")).scheme(new AsciiString("https")).authority(new AsciiString("example.org")).path(new AsciiString("/some/path/resource2")).add(HttpHeaderNames.COOKIE, "a=b").add(HttpHeaderNames.COOKIE, "c=d").add(HttpHeaderNames.COOKIE, "e=f");
        runInChannel(clientChannel, new Http2Runnable() {

            @Override
            public void run() throws Http2Exception {
                clientHandler.encoder().writeHeaders(ctxClient(), 3, http2Headers, 0, true, newPromiseClient());
                clientChannel.flush();
            }
        });
        awaitRequests();
        ArgumentCaptor<FullHttpMessage> requestCaptor = ArgumentCaptor.forClass(FullHttpMessage.class);
        verify(serverListener).messageReceived(requestCaptor.capture());
        capturedRequests = requestCaptor.getAllValues();
        assertEquals(request, capturedRequests.get(0));
    } finally {
        request.release();
    }
}
Also used : HttpHeaders(io.netty.handler.codec.http.HttpHeaders) DefaultFullHttpRequest(io.netty.handler.codec.http.DefaultFullHttpRequest) FullHttpRequest(io.netty.handler.codec.http.FullHttpRequest) Http2CodecUtil.getEmbeddedHttp2Exception(io.netty.handler.codec.http2.Http2CodecUtil.getEmbeddedHttp2Exception) DefaultFullHttpRequest(io.netty.handler.codec.http.DefaultFullHttpRequest) Http2Runnable(io.netty.handler.codec.http2.Http2TestUtil.Http2Runnable) FullHttpMessage(io.netty.handler.codec.http.FullHttpMessage) AsciiString(io.netty.util.AsciiString) Test(org.junit.jupiter.api.Test)

Example 57 with Http2Exception

use of io.netty.handler.codec.http2.Http2Exception in project zuul by Netflix.

the class Http2ConnectionCloseHandler method gracefullyWithDelay.

/**
 * WARNING: Found the OkHttp client gets confused by this behaviour (it ends up putting itself in a bad shutdown state
 * after receiving the first goaway frame, and then dropping any inflight responses but also timing out waiting for them).
 *
 * And worried that other http/2 stacks may be similar, so for now we should NOT use this.
 *
 * This is unfortunate, as FTL wanted this, and it is correct according to the spec.
 *
 * See this code in okhttp where it drops response header frame if state is already shutdown:
 * https://github.com/square/okhttp/blob/master/okhttp/src/main/java/okhttp3/internal/http2/Http2Connection.java#L609
 */
private void gracefullyWithDelay(EventExecutor executor, Channel parent, ChannelPromise promise) {
    // See javadoc for explanation of why this may be disabled.
    boolean allowGracefulDelayed = ConnectionCloseChannelAttributes.allowGracefulDelayed(parent);
    if (!allowGracefulDelayed) {
        immediate(parent, promise);
        return;
    }
    if (!parent.isActive()) {
        promise.setSuccess();
        return;
    }
    // First send a 'graceful shutdown' GOAWAY frame.
    /*
        "A server that is attempting to gracefully shut down a connection SHOULD send an initial GOAWAY frame with
        the last stream identifier set to 231-1 and a NO_ERROR code. This signals to the client that a shutdown is
        imminent and that initiating further requests is prohibited."
          -- https://http2.github.io/http2-spec/#GOAWAY
         */
    DefaultHttp2GoAwayFrame goaway = new DefaultHttp2GoAwayFrame(Http2Error.NO_ERROR);
    goaway.setExtraStreamIds(Integer.MAX_VALUE);
    parent.writeAndFlush(goaway);
    LOG.debug("gracefullyWithDelay: flushed initial go_away frame. channel=" + parent.id().asShortText());
    // In N secs time, throw an error that causes the http2 codec to send another GOAWAY frame
    // (this time with accurate lastStreamId) and then close the connection.
    int gracefulCloseDelay = ConnectionCloseChannelAttributes.gracefulCloseDelay(parent);
    executor.schedule(() -> {
        // Check that the client hasn't already closed the connection (due to the earlier goaway we sent).
        if (parent.isActive()) {
            // NOTE - the netty Http2ConnectionHandler specifically does not send another goaway when we call
            // channel.close() if one has already been sent .... so when we want more than one sent, we need to do it
            // explicitly ourselves like this.
            LOG.debug("gracefullyWithDelay: firing graceful_shutdown event to make netty send a final go_away frame and then close connection. channel=" + parent.id().asShortText());
            Http2Exception h2e = new Http2Exception(Http2Error.NO_ERROR, Http2Exception.ShutdownHint.GRACEFUL_SHUTDOWN);
            parent.pipeline().fireExceptionCaught(h2e);
            parent.close().addListener(future -> {
                promise.setSuccess();
            });
        } else {
            promise.setSuccess();
        }
    }, gracefulCloseDelay, TimeUnit.SECONDS);
}
Also used : Http2Exception(io.netty.handler.codec.http2.Http2Exception) DefaultHttp2GoAwayFrame(io.netty.handler.codec.http2.DefaultHttp2GoAwayFrame)

Example 58 with Http2Exception

use of io.netty.handler.codec.http2.Http2Exception in project grpc-java by grpc.

the class NettyClientHandler method forcefulClose.

private void forcefulClose(final ChannelHandlerContext ctx, final ForcefulCloseCommand msg, ChannelPromise promise) throws Exception {
    connection().forEachActiveStream(new Http2StreamVisitor() {

        @Override
        public boolean visit(Http2Stream stream) throws Http2Exception {
            NettyClientStream.TransportState clientStream = clientStream(stream);
            Tag tag = clientStream != null ? clientStream.tag() : PerfMark.createTag();
            PerfMark.startTask("NettyClientHandler.forcefulClose", tag);
            PerfMark.linkIn(msg.getLink());
            try {
                if (clientStream != null) {
                    clientStream.transportReportStatus(msg.getStatus(), true, new Metadata());
                    resetStream(ctx, stream.id(), Http2Error.CANCEL.code(), ctx.newPromise());
                }
                stream.close();
                return true;
            } finally {
                PerfMark.stopTask("NettyClientHandler.forcefulClose", tag);
            }
        }
    });
    close(ctx, promise);
}
Also used : Http2Exception(io.netty.handler.codec.http2.Http2Exception) Http2StreamVisitor(io.netty.handler.codec.http2.Http2StreamVisitor) Metadata(io.grpc.Metadata) Http2Stream(io.netty.handler.codec.http2.Http2Stream) Tag(io.perfmark.Tag)

Example 59 with Http2Exception

use of io.netty.handler.codec.http2.Http2Exception in project grpc-java by grpc.

the class NettyClientHandler method goingAway.

/**
 * Handler for a GOAWAY being received. Fails any streams created after the
 * last known stream. May only be called during a read.
 */
private void goingAway(long errorCode, byte[] debugData) {
    Status finalStatus = statusFromH2Error(Status.Code.UNAVAILABLE, "GOAWAY shut down transport", errorCode, debugData);
    lifecycleManager.notifyGracefulShutdown(finalStatus);
    abruptGoAwayStatus = statusFromH2Error(Status.Code.UNAVAILABLE, "Abrupt GOAWAY closed unsent stream", errorCode, debugData);
    // While this _should_ be UNAVAILABLE, Netty uses the wrong stream id in the GOAWAY when it
    // fails streams due to HPACK failures (e.g., header list too large). To be more conservative,
    // we assume any sent streams may be related to the GOAWAY. This should rarely impact users
    // since the main time servers should use abrupt GOAWAYs is if there is a protocol error, and if
    // there wasn't a protocol error the error code was probably NO_ERROR which is mapped to
    // UNAVAILABLE. https://github.com/netty/netty/issues/10670
    final Status abruptGoAwayStatusConservative = statusFromH2Error(null, "Abrupt GOAWAY closed sent stream", errorCode, debugData);
    final boolean mayBeHittingNettyBug = errorCode != Http2Error.NO_ERROR.code();
    // Try to allocate as many in-flight streams as possible, to reduce race window of
    // https://github.com/grpc/grpc-java/issues/2562 . To be of any help, the server has to
    // gracefully shut down the connection with two GOAWAYs. gRPC servers generally send a PING
    // after the first GOAWAY, so they can very precisely detect when the GOAWAY has been
    // processed and thus this processing must be in-line before processing additional reads.
    // This can cause reentrancy, but should be minor since it is normal to handle writes in
    // response to a read. Also, the call stack is rather shallow at this point
    clientWriteQueue.drainNow();
    if (lifecycleManager.notifyShutdown(finalStatus)) {
        // This is for the only RPCs that are actually covered by the GOAWAY error code. All other
        // RPCs were not observed by the remote and so should be UNAVAILABLE.
        channelInactiveReason = statusFromH2Error(null, "Connection closed after GOAWAY", errorCode, debugData);
    }
    final int lastKnownStream = connection().local().lastStreamKnownByPeer();
    try {
        connection().forEachActiveStream(new Http2StreamVisitor() {

            @Override
            public boolean visit(Http2Stream stream) throws Http2Exception {
                if (stream.id() > lastKnownStream) {
                    NettyClientStream.TransportState clientStream = clientStream(stream);
                    if (clientStream != null) {
                        // RpcProgress _should_ be REFUSED, but are being conservative. See comment for
                        // abruptGoAwayStatusConservative. This does reduce our ability to perform transparent
                        // retries, but only if something else caused a connection failure.
                        RpcProgress progress = mayBeHittingNettyBug ? RpcProgress.PROCESSED : RpcProgress.REFUSED;
                        clientStream.transportReportStatus(abruptGoAwayStatusConservative, progress, false, new Metadata());
                    }
                    stream.close();
                }
                return true;
            }
        });
    } catch (Http2Exception e) {
        throw new RuntimeException(e);
    }
}
Also used : Status(io.grpc.Status) Http2Exception(io.netty.handler.codec.http2.Http2Exception) Http2StreamVisitor(io.netty.handler.codec.http2.Http2StreamVisitor) Metadata(io.grpc.Metadata) RpcProgress(io.grpc.internal.ClientStreamListener.RpcProgress) Http2Stream(io.netty.handler.codec.http2.Http2Stream)

Example 60 with Http2Exception

use of io.netty.handler.codec.http2.Http2Exception in project grpc-java by grpc.

the class NettyClientHandler method channelInactive.

/**
 * Handler for the Channel shutting down.
 */
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
    try {
        logger.fine("Network channel is closed");
        Status status = Status.UNAVAILABLE.withDescription("Network closed for unknown reason");
        lifecycleManager.notifyShutdown(status);
        final Status streamStatus;
        if (channelInactiveReason != null) {
            streamStatus = channelInactiveReason;
        } else {
            streamStatus = lifecycleManager.getShutdownStatus();
        }
        try {
            cancelPing(lifecycleManager.getShutdownThrowable());
            // Report status to the application layer for any open streams
            connection().forEachActiveStream(new Http2StreamVisitor() {

                @Override
                public boolean visit(Http2Stream stream) throws Http2Exception {
                    NettyClientStream.TransportState clientStream = clientStream(stream);
                    if (clientStream != null) {
                        clientStream.transportReportStatus(streamStatus, false, new Metadata());
                    }
                    return true;
                }
            });
        } finally {
            lifecycleManager.notifyTerminated(status);
        }
    } finally {
        // Close any open streams
        super.channelInactive(ctx);
        if (keepAliveManager != null) {
            keepAliveManager.onTransportTermination();
        }
    }
}
Also used : Status(io.grpc.Status) Http2Exception(io.netty.handler.codec.http2.Http2Exception) Http2StreamVisitor(io.netty.handler.codec.http2.Http2StreamVisitor) Metadata(io.grpc.Metadata) Http2Stream(io.netty.handler.codec.http2.Http2Stream)

Aggregations

ByteBuf (io.netty.buffer.ByteBuf)109 ChannelHandlerContext (io.netty.channel.ChannelHandlerContext)100 ChannelFuture (io.netty.channel.ChannelFuture)92 Test (org.junit.Test)89 Http2Exception (io.netty.handler.codec.http2.Http2Exception)85 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)81 AtomicReference (java.util.concurrent.atomic.AtomicReference)78 ByteArrayOutputStream (java.io.ByteArrayOutputStream)76 Channel (io.netty.channel.Channel)75 ChannelPipeline (io.netty.channel.ChannelPipeline)75 ArrayList (java.util.ArrayList)75 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)75 ChannelInitializer (io.netty.channel.ChannelInitializer)74 NioEventLoopGroup (io.netty.channel.nio.NioEventLoopGroup)74 HttpHeaderNames (io.netty.handler.codec.http.HttpHeaderNames)74 DefaultHttp2Headers (io.netty.handler.codec.http2.DefaultHttp2Headers)74 Http2Headers (io.netty.handler.codec.http2.Http2Headers)74 ApplicationProtocolNames (io.netty.handler.ssl.ApplicationProtocolNames)74 ApplicationProtocolNegotiationHandler (io.netty.handler.ssl.ApplicationProtocolNegotiationHandler)74 SslHandler (io.netty.handler.ssl.SslHandler)74