diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/HttpServerUpgradeHandler.java b/codec-http/src/main/java/io/netty/handler/codec/http/HttpServerUpgradeHandler.java index 88aa739b298..2aa6e157d56 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/HttpServerUpgradeHandler.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/HttpServerUpgradeHandler.java @@ -323,7 +323,7 @@ private boolean upgrade(final ChannelHandlerContext ctx, final FullHttpRequest r // Make sure the CONNECTION header is present. List connectionHeaderValues = request.headers().getAll(HttpHeaderNames.CONNECTION); - if (connectionHeaderValues == null) { + if (connectionHeaderValues == null || connectionHeaderValues.isEmpty()) { return false; } diff --git a/codec-http/src/test/java/io/netty/handler/codec/http/HttpServerUpgradeHandlerTest.java b/codec-http/src/test/java/io/netty/handler/codec/http/HttpServerUpgradeHandlerTest.java index bc4552afb4f..a2e27e787f6 100644 --- a/codec-http/src/test/java/io/netty/handler/codec/http/HttpServerUpgradeHandlerTest.java +++ b/codec-http/src/test/java/io/netty/handler/codec/http/HttpServerUpgradeHandlerTest.java @@ -31,6 +31,7 @@ import io.netty.handler.codec.http.HttpServerUpgradeHandler.UpgradeCodec; import io.netty.handler.codec.http.HttpServerUpgradeHandler.UpgradeCodecFactory; import io.netty.util.CharsetUtil; +import io.netty.util.ReferenceCountUtil; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -189,4 +190,42 @@ protected boolean shouldHandleUpgradeRequest(HttpRequest req) { assertNull(channel.readOutbound()); assertFalse(channel.finishAndReleaseAll()); } + + @Test + public void upgradeFail() { + final HttpServerCodec httpServerCodec = new HttpServerCodec(); + final UpgradeCodecFactory factory = new UpgradeCodecFactory() { + @Override + public UpgradeCodec newUpgradeCodec(CharSequence protocol) { + return new TestUpgradeCodec(); + } + }; + + HttpServerUpgradeHandler upgradeHandler = new HttpServerUpgradeHandler(httpServerCodec, factory); + + EmbeddedChannel channel = new EmbeddedChannel(httpServerCodec, upgradeHandler); + + // Build a h2c upgrade request, but without connection header. + String upgradeString = "GET / HTTP/1.1\r\n" + + "Host: example.com\r\n" + + "Upgrade: h2c\r\n\r\n"; + ByteBuf upgrade = Unpooled.copiedBuffer(upgradeString, CharsetUtil.US_ASCII); + + assertTrue(channel.writeInbound(upgrade)); + assertNotNull(channel.pipeline().get(HttpServerCodec.class)); + assertNotNull(channel.pipeline().get(HttpServerUpgradeHandler.class)); // Should not be removed. + assertNull(channel.pipeline().get("marker")); + + HttpRequest req = channel.readInbound(); + assertEquals(HttpVersion.HTTP_1_1, req.protocolVersion()); + assertTrue(req.headers().contains(HttpHeaderNames.UPGRADE, "h2c", false)); + assertFalse(req.headers().contains(HttpHeaderNames.CONNECTION)); + ReferenceCountUtil.release(req); + assertNull(channel.readInbound()); + + // No response should be written because we're just passing through. + channel.flushOutbound(); + assertNull(channel.readOutbound()); + assertFalse(channel.finishAndReleaseAll()); + } }