io.netty.handler.codec.http.FullHttpRequest # release ( ) 源码实例Demo

下面列出了 io.netty.handler.codec.http.FullHttpRequest # release ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。


@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
    FullHttpRequest request = (msg instanceof FullHttpRequest) ? (FullHttpRequest) msg : null;
    
    // Check for invalid http messages during handshake
    if (request != null && handshakeInProgress) {
        request.release();
        sendBadRequestAndClose(ctx, null);
        return;
    }
    
    // Transform this when we have an upgrade for our path,
    // otherwise pass the message
    if (request != null && isUpgradeRequest(request)) {
        try {
            tryWebsocketHandshake(ctx, (FullHttpRequest) msg);
        } finally {
            request.release();
        }
    } else {
        ctx.fireChannelRead(msg);
    }
}
 
源代码2 项目: netty-4.1.22   文件: HttpConversionUtil.java

/**
 * Create a new object to contain the request data
 *
 * @param streamId The stream associated with the request
 * @param http2Headers The initial set of HTTP/2 headers to create the request with
 * @param alloc The {@link ByteBufAllocator} to use to generate the content of the message
 * @param validateHttpHeaders <ul>
 *        <li>{@code true} to validate HTTP headers in the http-codec</li>
 *        <li>{@code false} not to validate HTTP headers in the http-codec</li>
 *        </ul>
 * @return A new request object which represents headers/data
 * @throws Http2Exception see {@link #addHttp2ToHttpHeaders(int, Http2Headers, FullHttpMessage, boolean)}
 */
public static FullHttpRequest toFullHttpRequest(int streamId, Http2Headers http2Headers, ByteBufAllocator alloc,
                                            boolean validateHttpHeaders)
                throws Http2Exception {
    // HTTP/2 does not define a way to carry the version identifier that is included in the HTTP/1.1 request line.
    final CharSequence method = checkNotNull(http2Headers.method(),
            "method header cannot be null in conversion to HTTP/1.x");
    final CharSequence path = checkNotNull(http2Headers.path(),
            "path header cannot be null in conversion to HTTP/1.x");
    FullHttpRequest msg = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.valueOf(method
                    .toString()), path.toString(), alloc.buffer(), validateHttpHeaders);
    try {
        addHttp2ToHttpHeaders(streamId, http2Headers, msg, false);
    } catch (Http2Exception e) {
        msg.release();
        throw e;
    } catch (Throwable t) {
        msg.release();
        throw streamError(streamId, PROTOCOL_ERROR, t, "HTTP/2 to HTTP/1.x headers conversion error");
    }
    return msg;
}
 

@Test
public void testDowngradeFullHeaders() throws Exception {
    EmbeddedChannel ch = new EmbeddedChannel(new Http2StreamFrameToHttpObjectCodec(true));
    Http2Headers headers = new DefaultHttp2Headers();
    headers.path("/");
    headers.method("GET");

    assertTrue(ch.writeInbound(new DefaultHttp2HeadersFrame(headers, true)));

    FullHttpRequest request = ch.readInbound();
    try {
        assertThat(request.uri(), is("/"));
        assertThat(request.method(), is(HttpMethod.GET));
        assertThat(request.protocolVersion(), is(HttpVersion.HTTP_1_1));
        assertThat(request.content().readableBytes(), is(0));
        assertTrue(request.trailingHeaders().isEmpty());
        assertFalse(HttpUtil.isTransferEncodingChunked(request));
    } finally {
        request.release();
    }

    assertThat(ch.readInbound(), is(nullValue()));
    assertFalse(ch.finish());
}
 

@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
    FullHttpRequest request = (msg instanceof FullHttpRequest) ? (FullHttpRequest) msg : null;

    // Check for invalid http messages during handshake
    if (request != null && handshakeInProgress) {
        request.release();
        sendBadRequestAndClose(ctx, null);
        return;
    }

    // Transform this when we have an upgrade for our path,
    // otherwise pass the message
    if (request != null && isUpgradeRequest(request)) {
        try {
            tryWebsocketHandshake(ctx, (FullHttpRequest) msg);
        } finally {
            request.release();
        }
    } else {
        ctx.fireChannelRead(msg);
    }
}
 

protected void testHeaderDefaultHttp(String uri, CharSequence header, String expectedValue) {
    WebSocketClientHandshaker handshaker = newHandshaker(URI.create(uri));
    FullHttpRequest request = handshaker.newHandshakeRequest();
    try {
        assertEquals(expectedValue, request.headers().get(header));
    } finally {
        request.release();
    }
}
 

@Test
@SuppressWarnings("deprecation")
public void testRawPath() {
    URI uri = URI.create("ws://localhost:9999/path%20with%20ws");
    WebSocketClientHandshaker handshaker = newHandshaker(uri);
    FullHttpRequest request = handshaker.newHandshakeRequest();
    try {
        assertEquals("/path%20with%20ws", request.getUri());
    } finally {
        request.release();
    }
}
 

private static void testPerformOpeningHandshake0(boolean subProtocol) {
    EmbeddedChannel ch = new EmbeddedChannel(
            new HttpObjectAggregator(42), new HttpRequestDecoder(), new HttpResponseEncoder());

    FullHttpRequest req = new DefaultFullHttpRequest(HTTP_1_1, HttpMethod.GET, "/chat");
    req.headers().set(HttpHeaderNames.HOST, "server.example.com");
    req.headers().set(HttpHeaderNames.UPGRADE, HttpHeaderValues.WEBSOCKET);
    req.headers().set(HttpHeaderNames.CONNECTION, "Upgrade");
    req.headers().set(HttpHeaderNames.SEC_WEBSOCKET_KEY, "dGhlIHNhbXBsZSBub25jZQ==");
    req.headers().set(HttpHeaderNames.SEC_WEBSOCKET_ORIGIN, "http://example.com");
    req.headers().set(HttpHeaderNames.SEC_WEBSOCKET_PROTOCOL, "chat, superchat");
    req.headers().set(HttpHeaderNames.SEC_WEBSOCKET_VERSION, "8");

    if (subProtocol) {
        new WebSocketServerHandshaker08(
                "ws://example.com/chat", "chat", false, Integer.MAX_VALUE, false).handshake(ch, req);
    } else {
        new WebSocketServerHandshaker08(
                "ws://example.com/chat", null, false, Integer.MAX_VALUE, false).handshake(ch, req);
    }

    ByteBuf resBuf = ch.readOutbound();

    EmbeddedChannel ch2 = new EmbeddedChannel(new HttpResponseDecoder());
    ch2.writeInbound(resBuf);
    HttpResponse res = ch2.readInbound();

    Assert.assertEquals(
            "s3pPLMBiTxaQ9kYGzzhZRbK+xOo=", res.headers().get(HttpHeaderNames.SEC_WEBSOCKET_ACCEPT));
    if (subProtocol) {
        Assert.assertEquals("chat", res.headers().get(HttpHeaderNames.SEC_WEBSOCKET_PROTOCOL));
    } else {
        Assert.assertNull(res.headers().get(HttpHeaderNames.SEC_WEBSOCKET_PROTOCOL));
    }
    ReferenceCountUtil.release(res);
    req.release();
}
 

private static void testPerformOpeningHandshake0(boolean subProtocol) {
    EmbeddedChannel ch = new EmbeddedChannel(
            new HttpObjectAggregator(42), new HttpRequestDecoder(), new HttpResponseEncoder());

    FullHttpRequest req = new DefaultFullHttpRequest(
            HTTP_1_1, HttpMethod.GET, "/chat", Unpooled.copiedBuffer("^n:ds[4U", CharsetUtil.US_ASCII));

    req.headers().set(HttpHeaderNames.HOST, "server.example.com");
    req.headers().set(HttpHeaderNames.UPGRADE, HttpHeaderValues.WEBSOCKET);
    req.headers().set(HttpHeaderNames.CONNECTION, "Upgrade");
    req.headers().set(HttpHeaderNames.ORIGIN, "http://example.com");
    req.headers().set(HttpHeaderNames.SEC_WEBSOCKET_KEY1, "4 @1  46546xW%0l 1 5");
    req.headers().set(HttpHeaderNames.SEC_WEBSOCKET_KEY2, "12998 5 Y3 1  .P00");
    req.headers().set(HttpHeaderNames.SEC_WEBSOCKET_PROTOCOL, "chat, superchat");

    if (subProtocol) {
        new WebSocketServerHandshaker00(
                "ws://example.com/chat", "chat", Integer.MAX_VALUE).handshake(ch, req);
    } else {
        new WebSocketServerHandshaker00(
                "ws://example.com/chat", null, Integer.MAX_VALUE).handshake(ch, req);
    }

    EmbeddedChannel ch2 = new EmbeddedChannel(new HttpResponseDecoder());
    ch2.writeInbound(ch.readOutbound());
    HttpResponse res = ch2.readInbound();

    Assert.assertEquals("ws://example.com/chat", res.headers().get(HttpHeaderNames.SEC_WEBSOCKET_LOCATION));

    if (subProtocol) {
        Assert.assertEquals("chat", res.headers().get(HttpHeaderNames.SEC_WEBSOCKET_PROTOCOL));
    } else {
        Assert.assertNull(res.headers().get(HttpHeaderNames.SEC_WEBSOCKET_PROTOCOL));
    }
    LastHttpContent content = ch2.readInbound();

    Assert.assertEquals("8jKS'y:G*Co,Wxa-", content.content().toString(CharsetUtil.US_ASCII));
    content.release();
    req.release();
}
 

private static void testPerformOpeningHandshake0(boolean subProtocol) {
    EmbeddedChannel ch = new EmbeddedChannel(
            new HttpObjectAggregator(42), new HttpRequestDecoder(), new HttpResponseEncoder());

    FullHttpRequest req = new DefaultFullHttpRequest(HTTP_1_1, HttpMethod.GET, "/chat");
    req.headers().set(HttpHeaderNames.HOST, "server.example.com");
    req.headers().set(HttpHeaderNames.UPGRADE, HttpHeaderValues.WEBSOCKET);
    req.headers().set(HttpHeaderNames.CONNECTION, "Upgrade");
    req.headers().set(HttpHeaderNames.SEC_WEBSOCKET_KEY, "dGhlIHNhbXBsZSBub25jZQ==");
    req.headers().set(HttpHeaderNames.SEC_WEBSOCKET_ORIGIN, "http://example.com");
    req.headers().set(HttpHeaderNames.SEC_WEBSOCKET_PROTOCOL, "chat, superchat");
    req.headers().set(HttpHeaderNames.SEC_WEBSOCKET_VERSION, "13");

    if (subProtocol) {
        new WebSocketServerHandshaker13(
                "ws://example.com/chat", "chat", false, Integer.MAX_VALUE, false).handshake(ch, req);
    } else {
        new WebSocketServerHandshaker13(
                "ws://example.com/chat", null, false, Integer.MAX_VALUE, false).handshake(ch, req);
    }

    ByteBuf resBuf = ch.readOutbound();

    EmbeddedChannel ch2 = new EmbeddedChannel(new HttpResponseDecoder());
    ch2.writeInbound(resBuf);
    HttpResponse res = ch2.readInbound();

    Assert.assertEquals(
            "s3pPLMBiTxaQ9kYGzzhZRbK+xOo=", res.headers().get(HttpHeaderNames.SEC_WEBSOCKET_ACCEPT));
    if (subProtocol) {
        Assert.assertEquals("chat", res.headers().get(HttpHeaderNames.SEC_WEBSOCKET_PROTOCOL));
    } else {
        Assert.assertNull(res.headers().get(HttpHeaderNames.SEC_WEBSOCKET_PROTOCOL));
    }
    ReferenceCountUtil.release(res);
    req.release();
}
 
源代码10 项目: netty-4.1.22   文件: HttpProxyHandlerTest.java

private static void testInitialMessage(InetSocketAddress socketAddress, String hostPort,
                                       HttpHeaders headers) throws Exception  {
    InetSocketAddress proxyAddress = new InetSocketAddress(NetUtil.LOCALHOST, 8080);

    ChannelPromise promise = mock(ChannelPromise.class);
    verifyNoMoreInteractions(promise);

    ChannelHandlerContext ctx = mock(ChannelHandlerContext.class);
    when(ctx.connect(same(proxyAddress), isNull(InetSocketAddress.class), same(promise))).thenReturn(promise);

    HttpProxyHandler handler = new HttpProxyHandler(new InetSocketAddress(NetUtil.LOCALHOST, 8080), headers);
    handler.connect(ctx, socketAddress, null, promise);

    FullHttpRequest request = (FullHttpRequest) handler.newInitialMessage(ctx);
    try {
        assertEquals(HttpVersion.HTTP_1_1, request.protocolVersion());
        assertEquals(hostPort, request.uri());
        HttpHeaders actualHeaders = request.headers();
        assertEquals(hostPort, actualHeaders.get(HttpHeaderNames.HOST));

        if (headers != null) {
            // The actual request header is a strict superset of the custom header
            for (String name : headers.names()) {
                assertEquals(headers.getAll(name), actualHeaders.getAll(name));
            }
        }
    } finally {
        request.release();
    }
    verify(ctx).connect(proxyAddress, null, promise);
}
 

@Test
public void clientRequestSingleHeaderNoDataFrames() 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.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"));
        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();
    }
}
 

@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();
    }
}
 

@Test
public void clientRequestSingleHeaderCookieSplitIntoMultipleEntries2() 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; 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();
    }
}
 

@Override
public void channelRead(final ChannelHandlerContext ctx, Object msg) throws Exception {
    FullHttpRequest req = (FullHttpRequest) msg;
    try {
        if (req.getMethod() != GET) {
            sendHttpResponse(ctx, req, new DefaultFullHttpResponse(HTTP_1_1, FORBIDDEN));
            return;
        }

        final WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory(
                getWebSocketLocation(ctx.pipeline(), req, websocketPath), subprotocols,
                        allowExtensions, maxFramePayloadSize);
        final WebSocketServerHandshaker handshaker = wsFactory.newHandshaker(req);
        if (handshaker == null) {
            WebSocketServerHandshakerFactory.sendUnsupportedVersionResponse(ctx.channel());
        } else {
            final ChannelFuture handshakeFuture = handshaker.handshake(ctx.channel(), req);
            handshakeFuture.addListener(new ChannelFutureListener() {
                @Override
                public void operationComplete(ChannelFuture future) throws Exception {
                    if (!future.isSuccess()) {
                        ctx.fireExceptionCaught(future.cause());
                    } else {
                        ctx.fireUserEventTriggered(
                                WebSocketServerProtocolHandler.ServerHandshakeStateEvent.HANDSHAKE_COMPLETE);
                    }
                }
            });
            WebSocketServerProtocolHandler.setHandshaker(ctx, handshaker);
            ctx.pipeline().replace(this, "WS403Responder",
                    WebSocketServerProtocolHandler.forbiddenHttpRequestResponder());
        }
    } finally {
        req.release();
    }
}
 

@Test
public void clientRequestMultipleDataFrames() throws Exception {
    boostrapEnv(1, 1, 1);
    final String text = "hello world big time data!";
    final ByteBuf content = Unpooled.copiedBuffer(text.getBytes());
    final FullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET,
            "/some/path/resource2", content, true);
    try {
        HttpHeaders httpHeaders = request.headers();
        httpHeaders.setInt(HttpConversionUtil.ExtensionHeaderNames.STREAM_ID.text(), 3);
        httpHeaders.setInt(HttpHeaderNames.CONTENT_LENGTH, text.length());
        httpHeaders.setShort(HttpConversionUtil.ExtensionHeaderNames.STREAM_WEIGHT.text(), (short) 16);
        final Http2Headers http2Headers = new DefaultHttp2Headers().method(new AsciiString("GET")).path(
                new AsciiString("/some/path/resource2"));
        final int midPoint = text.length() / 2;
        runInChannel(clientChannel, new Http2Runnable() {
            @Override
            public void run() throws Http2Exception {
                clientHandler.encoder().writeHeaders(ctxClient(), 3, http2Headers, 0, false, newPromiseClient());
                clientHandler.encoder().writeData(
                        ctxClient(), 3, content.retainedSlice(0, midPoint), 0, false, newPromiseClient());
                clientHandler.encoder().writeData(
                        ctxClient(), 3, content.retainedSlice(midPoint, text.length() - midPoint),
                        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();
    }
}
 

@Test
public void clientRequestMultipleEmptyDataFrames() throws Exception {
    boostrapEnv(1, 1, 1);
    final String text = "";
    final ByteBuf content = Unpooled.copiedBuffer(text.getBytes());
    final FullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET,
            "/some/path/resource2", content, true);
    try {
        HttpHeaders httpHeaders = request.headers();
        httpHeaders.setInt(HttpConversionUtil.ExtensionHeaderNames.STREAM_ID.text(), 3);
        httpHeaders.setInt(HttpHeaderNames.CONTENT_LENGTH, text.length());
        httpHeaders.setShort(HttpConversionUtil.ExtensionHeaderNames.STREAM_WEIGHT.text(), (short) 16);
        final Http2Headers http2Headers = new DefaultHttp2Headers().method(new AsciiString("GET")).path(
                new AsciiString("/some/path/resource2"));
        runInChannel(clientChannel, new Http2Runnable() {
            @Override
            public void run() throws Http2Exception {
                clientHandler.encoder().writeHeaders(ctxClient(), 3, http2Headers, 0, false, newPromiseClient());
                clientHandler.encoder().writeData(ctxClient(), 3, content.retain(), 0, false, newPromiseClient());
                clientHandler.encoder().writeData(ctxClient(), 3, content.retain(), 0, false, newPromiseClient());
                clientHandler.encoder().writeData(ctxClient(), 3, content.retain(), 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();
    }
}
 

@Override
public synchronized void filter(Channel channel) throws Exception {
    HttpRequestBuilder httpRequestBuilder = config.getHttpRequestBuilder()
            .setRouteMapper(config.getRouteMapper());

    FullHttpRequest httpRequest = ContextUtil.getRequest(channel);
    RequestHolder requestHolder = httpRequestBuilder.build(httpRequest);
    httpRequest.release();
    ContextUtil.setRequestHolder(channel, requestHolder);

    BackClientPool.INSTANCE.request(requestHolder, channel);
}
 

@Override
protected void onInboundNext(ChannelHandlerContext ctx, Object msg) {
	if (msg instanceof HttpRequest) {
		try {
			listener().onStateChange(this, HttpServerState.REQUEST_RECEIVED);
		}
		catch (Exception e) {
			onInboundError(e);
			ReferenceCountUtil.release(msg);
			return;
		}
		if (msg instanceof FullHttpRequest) {
			FullHttpRequest request = (FullHttpRequest) msg;
			if (request.content().readableBytes() > 0) {
				super.onInboundNext(ctx, msg);
			}
			else {
				request.release();
			}
			if (isHttp2()) {
				//force auto read to enable more accurate close selection now inbound is done
				channel().config().setAutoRead(true);
				onInboundComplete();
			}
		}
		return;
	}
	if (msg instanceof HttpContent) {
		if (msg != LastHttpContent.EMPTY_LAST_CONTENT) {
			super.onInboundNext(ctx, msg);
		}
		if (msg instanceof LastHttpContent) {
			//force auto read to enable more accurate close selection now inbound is done
			channel().config().setAutoRead(true);
			onInboundComplete();
		}
	}
	else {
		super.onInboundNext(ctx, msg);
	}
}
 

@Test
public void clientRequestTrailingHeaders() throws Exception {
    boostrapEnv(1, 1, 1);
    final String text = "some data";
    final ByteBuf content = Unpooled.copiedBuffer(text.getBytes());
    final FullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET,
            "/some/path/resource2", content, true);
    try {
        HttpHeaders httpHeaders = request.headers();
        httpHeaders.setInt(HttpConversionUtil.ExtensionHeaderNames.STREAM_ID.text(), 3);
        httpHeaders.setInt(HttpHeaderNames.CONTENT_LENGTH, text.length());
        httpHeaders.setShort(HttpConversionUtil.ExtensionHeaderNames.STREAM_WEIGHT.text(), (short) 16);
        HttpHeaders trailingHeaders = request.trailingHeaders();
        trailingHeaders.set(of("Foo"), of("goo"));
        trailingHeaders.set(of("fOo2"), of("goo2"));
        trailingHeaders.add(of("foO2"), of("goo3"));
        final Http2Headers http2Headers = new DefaultHttp2Headers().method(new AsciiString("GET")).path(
                new AsciiString("/some/path/resource2"));
        final Http2Headers http2Headers2 = new DefaultHttp2Headers()
                .set(new AsciiString("foo"), new AsciiString("goo"))
                .set(new AsciiString("foo2"), new AsciiString("goo2"))
                .add(new AsciiString("foo2"), new AsciiString("goo3"));
        runInChannel(clientChannel, new Http2Runnable() {
            @Override
            public void run() throws Http2Exception {
                clientHandler.encoder().writeHeaders(ctxClient(), 3, http2Headers, 0, false, newPromiseClient());
                clientHandler.encoder().writeData(ctxClient(), 3, content.retainedDuplicate(), 0, false,
                                                  newPromiseClient());
                clientHandler.encoder().writeHeaders(ctxClient(), 3, http2Headers2, 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();
    }
}
 

@Test
public void clientRequestStreamDependencyInHttpMessageFlow() throws Exception {
    boostrapEnv(1, 2, 1);
    final String text = "hello world big time data!";
    final ByteBuf content = Unpooled.copiedBuffer(text.getBytes());
    final String text2 = "hello world big time data...number 2!!";
    final ByteBuf content2 = Unpooled.copiedBuffer(text2.getBytes());
    final FullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.PUT,
            "/some/path/resource", content, true);
    final FullHttpMessage request2 = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.PUT,
            "/some/path/resource2", content2, true);
    try {
        HttpHeaders httpHeaders = request.headers();
        httpHeaders.setInt(HttpConversionUtil.ExtensionHeaderNames.STREAM_ID.text(), 3);
        httpHeaders.setInt(HttpHeaderNames.CONTENT_LENGTH, text.length());
        httpHeaders.setShort(HttpConversionUtil.ExtensionHeaderNames.STREAM_WEIGHT.text(), (short) 16);
        HttpHeaders httpHeaders2 = request2.headers();
        httpHeaders2.setInt(HttpConversionUtil.ExtensionHeaderNames.STREAM_ID.text(), 5);
        httpHeaders2.setInt(HttpConversionUtil.ExtensionHeaderNames.STREAM_DEPENDENCY_ID.text(), 3);
        httpHeaders2.setShort(HttpConversionUtil.ExtensionHeaderNames.STREAM_WEIGHT.text(), (short) 123);
        httpHeaders2.setInt(HttpHeaderNames.CONTENT_LENGTH, text2.length());
        final Http2Headers http2Headers = new DefaultHttp2Headers().method(new AsciiString("PUT")).path(
                new AsciiString("/some/path/resource"));
        final Http2Headers http2Headers2 = new DefaultHttp2Headers().method(new AsciiString("PUT")).path(
                new AsciiString("/some/path/resource2"));
        runInChannel(clientChannel, new Http2Runnable() {
            @Override
            public void run() throws Http2Exception {
                clientHandler.encoder().writeHeaders(ctxClient(), 3, http2Headers, 0, false, newPromiseClient());
                clientHandler.encoder().writeHeaders(ctxClient(), 5, http2Headers2, 3, (short) 123, true, 0,
                        false, newPromiseClient());
                clientChannel.flush(); // Headers are queued in the flow controller and so flush them.
                clientHandler.encoder().writeData(ctxClient(), 3, content.retainedDuplicate(), 0, true,
                                                  newPromiseClient());
                clientHandler.encoder().writeData(ctxClient(), 5, content2.retainedDuplicate(), 0, true,
                                                  newPromiseClient());
                clientChannel.flush();
            }
        });
        awaitRequests();
        ArgumentCaptor<FullHttpMessage> httpObjectCaptor = ArgumentCaptor.forClass(FullHttpMessage.class);
        verify(serverListener, times(2)).messageReceived(httpObjectCaptor.capture());
        capturedRequests = httpObjectCaptor.getAllValues();
        assertEquals(request, capturedRequests.get(0));
        assertEquals(request2, capturedRequests.get(1));
    } finally {
        request.release();
        request2.release();
    }
}