server h2c upgrade fail when request doesn't have connection header (#11569)

__Motivation__
Since request.headers().getAll() will never return null. And the check null condition will not work as expected.

__Modification__

Add isEmpty() checking as well.

__Result__

Fixes #11568
This commit is contained in:
DD 2021-08-13 00:04:18 +08:00 committed by NiteshKant
parent 25699e44e9
commit 85b0eb2d3e
2 changed files with 40 additions and 1 deletions

View File

@ -320,7 +320,7 @@ public class HttpServerUpgradeHandler extends HttpObjectAggregator {
// Make sure the CONNECTION header is present.
List<String> connectionHeaderValues = request.headers().getAll(HttpHeaderNames.CONNECTION);
if (connectionHeaderValues == null) {
if (connectionHeaderValues == null || connectionHeaderValues.isEmpty()) {
return false;
}

View File

@ -28,6 +28,7 @@ import io.netty.channel.embedded.EmbeddedChannel;
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;
@ -171,4 +172,42 @@ public class HttpServerUpgradeHandlerTest {
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());
}
}