HTTP/2 Writes GO_AWAY on channelInactive
Motivation: Http2ConnectionHandler inherits from ByteToMessageDecoder. ByteToMessageDecoder.channelInactive will attempt to decode any remaining data by calling the abstract decode method. If the Http2ConnectionHandler is in server mode, and no data has been exchanged yet, it will try to treat this data as an invalid connection preface and write a GO_AWAY. This is noisy in the logs and creates an illusion that there is a protocol violation when there has not been. Modifications: - If the channel is inactive the connection preface decode should not be executed. Result: Log files don't include misleading error messages related to connection preface errors.
This commit is contained in:
parent
23f7fc67a4
commit
83c4aa6ad8
@ -207,7 +207,7 @@ public class Http2ConnectionHandler extends ByteToMessageDecoder implements Http
|
||||
@Override
|
||||
public void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
|
||||
try {
|
||||
if (readClientPrefaceString(in) && verifyFirstFrameIsSettings(in)) {
|
||||
if (ctx.channel().isActive() && readClientPrefaceString(in) && verifyFirstFrameIsSettings(in)) {
|
||||
// After the preface is read, it is time to hand over control to the post initialized decoder.
|
||||
byteDecoder = new FrameDecoder();
|
||||
byteDecoder.decode(ctx, in, out);
|
||||
@ -735,8 +735,8 @@ public class Http2ConnectionHandler extends ByteToMessageDecoder implements Http
|
||||
ctx.close();
|
||||
}
|
||||
} else {
|
||||
if (logger.isErrorEnabled()) {
|
||||
logger.error("{} Sending GOAWAY failed: lastStreamId '{}', errorCode '{}', " +
|
||||
if (logger.isWarnEnabled()) {
|
||||
logger.warn("{} Sending GOAWAY failed: lastStreamId '{}', errorCode '{}', " +
|
||||
"debugData '{}'. Forcing shutdown of the connection.",
|
||||
ctx.channel(), lastStreamId, errorCode, debugData.toString(UTF_8), future.cause());
|
||||
}
|
||||
|
@ -436,6 +436,18 @@ public class Http2ConnectionHandlerTest {
|
||||
verify(ctx, times(1)).flush();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void channelClosedDoesNotThrowPrefaceException() throws Exception {
|
||||
when(connection.isServer()).thenReturn(true);
|
||||
handler = newHandler();
|
||||
when(channel.isActive()).thenReturn(false);
|
||||
handler.channelInactive(ctx);
|
||||
verify(frameWriter, never()).writeGoAway(any(ChannelHandlerContext.class), anyInt(), anyLong(),
|
||||
any(ByteBuf.class), any(ChannelPromise.class));
|
||||
verify(frameWriter, never()).writeRstStream(any(ChannelHandlerContext.class), anyInt(), anyLong(),
|
||||
any(ChannelPromise.class));
|
||||
}
|
||||
|
||||
private static ByteBuf dummyData() {
|
||||
return Unpooled.buffer().writeBytes("abcdefgh".getBytes(UTF_8));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user