Skip to content

Commit 16b98d3

Browse files
authored
Correctly handle http2 upgrades when Http2FrameCodec is used together… (netty#9318)
Motivation: In the latest release we introduced Http2MultiplexHandler as a replacement of Http2MultiplexCodec. This did split the frame parsing from the multiplexing to allow a more flexible way to handle frames and to make the code cleaner. Unfortunally we did miss to special handle this in Http2ServerUpgradeCodec and so did not correctly add Http2MultiplexHandler to the pipeline before calling Http2FrameCodec.onHttpServerUpgrade(...). This did lead to the situation that we did not correctly receive the event on the Http2MultiplexHandler and so did not correctly created the Http2StreamChannel for the upgrade stream. Because of this we ended up with an NPE if a frame was dispatched to the upgrade stream later on. Modifications: - Correctly add Http2MultiplexHandler to the pipeline before calling Http2FrameCodec.onHttpServerUpgrade(...) - Add unit test Result: Fixes netty#9314.
1 parent 1b82474 commit 16b98d3

File tree

2 files changed

+18
-9
lines changed

2 files changed

+18
-9
lines changed

codec-http2/src/main/java/io/netty/handler/codec/http2/Http2ServerUpgradeCodec.java

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -146,19 +146,19 @@ public void upgradeTo(final ChannelHandlerContext ctx, FullHttpRequest upgradeRe
146146
try {
147147
// Add the HTTP/2 connection handler to the pipeline immediately following the current handler.
148148
ctx.pipeline().addAfter(ctx.name(), handlerName, connectionHandler);
149-
connectionHandler.onHttpServerUpgrade(settings);
150149

150+
// Add also all extra handlers as these may handle events / messages produced by the connectionHandler.
151+
// See https://github.com/netty/netty/issues/9314
152+
if (handlers != null) {
153+
final String name = ctx.pipeline().context(connectionHandler).name();
154+
for (int i = handlers.length - 1; i >= 0; i--) {
155+
ctx.pipeline().addAfter(name, null, handlers[i]);
156+
}
157+
}
158+
connectionHandler.onHttpServerUpgrade(settings);
151159
} catch (Http2Exception e) {
152160
ctx.fireExceptionCaught(e);
153161
ctx.close();
154-
return;
155-
}
156-
157-
if (handlers != null) {
158-
final String name = ctx.pipeline().context(connectionHandler).name();
159-
for (int i = handlers.length - 1; i >= 0; i--) {
160-
ctx.pipeline().addAfter(name, null, handlers[i]);
161-
}
162162
}
163163
}
164164

codec-http2/src/test/java/io/netty/handler/codec/http2/Http2ServerUpgradeCodecTest.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,11 @@ private static void testUpgrade(Http2ConnectionHandler handler, ChannelHandler m
7676
// Flush the channel to ensure we write out all buffered data
7777
channel.flush();
7878

79+
channel.writeInbound(Http2CodecUtil.connectionPrefaceBuf());
80+
Http2FrameInboundWriter writer = new Http2FrameInboundWriter(channel);
81+
writer.writeInboundSettings(new Http2Settings());
82+
writer.writeInboundRstStream(Http2CodecUtil.HTTP_UPGRADE_STREAM_ID, Http2Error.CANCEL.code());
83+
7984
assertSame(handler, channel.pipeline().remove(handler.getClass()));
8085
assertNull(channel.pipeline().get(handler.getClass()));
8186
assertTrue(channel.finish());
@@ -85,6 +90,10 @@ private static void testUpgrade(Http2ConnectionHandler handler, ChannelHandler m
8590
assertNotNull(settingsBuffer);
8691
settingsBuffer.release();
8792

93+
ByteBuf buf = channel.readOutbound();
94+
assertNotNull(buf);
95+
buf.release();
96+
8897
assertNull(channel.readOutbound());
8998
}
9099

0 commit comments

Comments
 (0)