Setting server.max-http-request-header-size doesn't work when http2 is enabled on Netty server.
I have created a small repro project https://github.com/NersesAM/netty-http2-bug
Steps to reproduce:
- checkout https://github.com/NersesAM/netty-http2-bug
- Start the server NettyHttp2BugApplication. max-http-request-header-size in application.yml file is set to 16k
- Hit it with the following curl command which has forced http2 and header size ~9k which is over default 8K size.
curl -IXGET --http2-prior-knowledge --location "http://localhost:8080" \
-H "Accept: application/json" \
-H "large-header1: Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Id neque aliquam vestibulum morbi. Mattis vulputate enim nulla aliquet. Dignissim suspendisse in est ante in nibh mauris cursus mattis. Aliquet nec ullamcorper sit amet risus nullam eget felis. Nascetur ridiculus mus mauris vitae ultricies leo integer. Proin sagittis nisl rhoncus mattis rhoncus urna. Id diam vel quam elementum pulvinar etiam non. Ut venenatis tellus in metus vulputate eu scelerisque felis. Turpis egestas maecenas pharetra convallis posuere morbi. Tempor orci eu lobortis elementum nibh tellus molestie nunc. Mauris commodo quis imperdiet massa tincidunt. Et sollicitudin ac orci phasellus egestas. Consectetur lorem donec massa sapien faucibus et molestie ac feugiat. Pulvinar mattis nunc sed blandit libero volutpat sed. Nulla facilisi nullam vehicula ipsum a arcu cursus. Justo laoreet sit amet cursus sit amet.Eget lorem dolor sed viverra ipsum. Lacus sed turpis tincidunt id. Senectus et netus et malesuada fames ac turpis. Eget nullam non nisi est sit amet. Sed viverra ipsum nunc aliquet bibendum enim facilisis gravida. Cursus vitae congue mauris rhoncus aenean vel elit. Sit amet luctus venenatis lectus magna fringilla urna porttitor rhoncus. Nibh tortor id aliquet lectus proin nibh nisl condimentum. Risus viverra adipiscing at in tellus integer. Elit sed vulputate mi sit amet mauris commodo quis imperdiet. Arcu non odio euismod lacinia at quis risus. Purus gravida quis blandit turpis cursus. Dui sapien eget mi proin sed libero enim sed. Vel orci porta non pulvinar neque laoreet suspendisse interdum consectetur. Posuere urna nec tincidunt praesent semper feugiat. Tortor vitae purus faucibus ornare suspendisse sed. Risus commodo viverra maecenas accumsan lacus. Massa massa ultricies mi quis hendrerit dolor magna. Sed turpis tincidunt id aliquet risus feugiat in. Scelerisque felis imperdiet proin fermentum. Orci a scelerisque purus semper. Et molestie ac feugiat sed lectus. Amet nisl purus in mollis nunc. Dui sapien eget mi proin sed. Arcu odio ut sem nulla pharetra diam. Ipsum nunc aliquet bibendum enim. Tempor commodo ullamcorper a lacus vestibulum sed arcu non odio." \
-H "large-header2: Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Id neque aliquam vestibulum morbi. Mattis vulputate enim nulla aliquet. Dignissim suspendisse in est ante in nibh mauris cursus mattis. Aliquet nec ullamcorper sit amet risus nullam eget felis. Nascetur ridiculus mus mauris vitae ultricies leo integer. Proin sagittis nisl rhoncus mattis rhoncus urna. Id diam vel quam elementum pulvinar etiam non. Ut venenatis tellus in metus vulputate eu scelerisque felis. Turpis egestas maecenas pharetra convallis posuere morbi. Tempor orci eu lobortis elementum nibh tellus molestie nunc. Mauris commodo quis imperdiet massa tincidunt. Et sollicitudin ac orci phasellus egestas. Consectetur lorem donec massa sapien faucibus et molestie ac feugiat. Pulvinar mattis nunc sed blandit libero volutpat sed. Nulla facilisi nullam vehicula ipsum a arcu cursus. Justo laoreet sit amet cursus sit amet.Eget lorem dolor sed viverra ipsum. Lacus sed turpis tincidunt id. Senectus et netus et malesuada fames ac turpis. Eget nullam non nisi est sit amet. Sed viverra ipsum nunc aliquet bibendum enim facilisis gravida. Cursus vitae congue mauris rhoncus aenean vel elit. Sit amet luctus venenatis lectus magna fringilla urna porttitor rhoncus. Nibh tortor id aliquet lectus proin nibh nisl condimentum. Risus viverra adipiscing at in tellus integer. Elit sed vulputate mi sit amet mauris commodo quis imperdiet. Arcu non odio euismod lacinia at quis risus. Purus gravida quis blandit turpis cursus. Dui sapien eget mi proin sed libero enim sed. Vel orci porta non pulvinar neque laoreet suspendisse interdum consectetur. Posuere urna nec tincidunt praesent semper feugiat. Tortor vitae purus faucibus ornare suspendisse sed. Risus commodo viverra maecenas accumsan lacus. Massa massa ultricies mi quis hendrerit dolor magna. Sed turpis tincidunt id aliquet risus feugiat in. Scelerisque felis imperdiet proin fermentum. Orci a scelerisque purus semper. Et molestie ac feugiat sed lectus. Amet nisl purus in mollis nunc. Dui sapien eget mi proin sed. Arcu odio ut sem nulla pharetra diam. Ipsum nunc aliquet bibendum enim. Tempor commodo ullamcorper a lacus vestibulum sed arcu non odio." \
-H "large-header3: Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Id neque aliquam vestibulum morbi. Mattis vulputate enim nulla aliquet. Dignissim suspendisse in est ante in nibh mauris cursus mattis. Aliquet nec ullamcorper sit amet risus nullam eget felis. Nascetur ridiculus mus mauris vitae ultricies leo integer. Proin sagittis nisl rhoncus mattis rhoncus urna. Id diam vel quam elementum pulvinar etiam non. Ut venenatis tellus in metus vulputate eu scelerisque felis. Turpis egestas maecenas pharetra convallis posuere morbi. Tempor orci eu lobortis elementum nibh tellus molestie nunc. Mauris commodo quis imperdiet massa tincidunt. Et sollicitudin ac orci phasellus egestas. Consectetur lorem donec massa sapien faucibus et molestie ac feugiat. Pulvinar mattis nunc sed blandit libero volutpat sed. Nulla facilisi nullam vehicula ipsum a arcu cursus. Justo laoreet sit amet cursus sit amet.Eget lorem dolor sed viverra ipsum. Lacus sed turpis tincidunt id. Senectus et netus et malesuada fames ac turpis. Eget nullam non nisi est sit amet. Sed viverra ipsum nunc aliquet bibendum enim facilisis gravida. Cursus vitae congue mauris rhoncus aenean vel elit. Sit amet luctus venenatis lectus magna fringilla urna porttitor rhoncus. Nibh tortor id aliquet lectus proin nibh nisl condimentum. Risus viverra adipiscing at in tellus integer. Elit sed vulputate mi sit amet mauris commodo quis imperdiet. Arcu non odio euismod lacinia at quis risus. Purus gravida quis blandit turpis cursus. Dui sapien eget mi proin sed libero enim sed. Vel orci porta non pulvinar neque laoreet suspendisse interdum consectetur. Posuere urna nec tincidunt praesent semper feugiat. Tortor vitae purus faucibus ornare suspendisse sed. Risus commodo viverra maecenas accumsan lacus. Massa massa ultricies mi quis hendrerit dolor magna. Sed turpis tincidunt id aliquet risus feugiat in. Scelerisque felis imperdiet proin fermentum. Orci a scelerisque purus semper. Et molestie ac feugiat sed lectus. Amet nisl purus in mollis nunc. Dui sapien eget mi proin sed. Arcu odio ut sem nulla pharetra diam. Ipsum nunc aliquet bibendum enim. Tempor commodo ullamcorper a lacus vestibulum sed arcu non odio." \
-H "large-header4: Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Id neque aliquam vestibulum morbi. Mattis vulputate enim nulla aliquet. Dignissim suspendisse in est ante in nibh mauris cursus mattis. Aliquet nec ullamcorper sit amet risus nullam eget felis. Nascetur ridiculus mus mauris vitae ultricies leo integer. Proin sagittis nisl rhoncus mattis rhoncus urna. Id diam vel quam elementum pulvinar etiam non. Ut venenatis tellus in metus vulputate eu scelerisque felis. Turpis egestas maecenas pharetra convallis posuere morbi. Tempor orci eu lobortis elementum nibh tellus molestie nunc. Mauris commodo quis imperdiet massa tincidunt. Et sollicitudin ac orci phasellus egestas. Consectetur lorem donec massa sapien faucibus et molestie ac feugiat. Pulvinar mattis nunc sed blandit libero volutpat sed. Nulla facilisi nullam vehicula ipsum a arcu cursus. Justo laoreet sit amet cursus sit amet.Eget lorem dolor sed viverra ipsum. Lacus sed turpis tincidunt id. Senectus et netus et malesuada fames ac turpis. Eget nullam non nisi est sit amet. Sed viverra ipsum nunc aliquet bibendum enim facilisis gravida. Cursus vitae congue mauris rhoncus aenean vel elit. Sit amet luctus venenatis lectus magna fringilla urna porttitor rhoncus. Nibh tortor id aliquet lectus proin nibh nisl condimentum. Risus viverra adipiscing at in tellus integer. Elit sed vulputate mi sit amet mauris commodo quis imperdiet. Arcu non odio euismod lacinia at quis risus. Purus gravida quis blandit turpis cursus. Dui sapien eget mi proin sed libero enim sed. Vel orci porta non pulvinar neque laoreet suspendisse interdum consectetur. Posuere urna nec tincidunt praesent semper feugiat. Tortor vitae purus faucibus ornare suspendisse sed. Risus commodo viverra maecenas accumsan lacus. Massa massa ultricies mi quis hendrerit dolor magna. Sed turpis tincidunt id aliquet risus feugiat in. Scelerisque felis imperdiet proin fermentum. Orci a scelerisque purus semper. Et molestie ac feugiat sed lectus. Amet nisl purus in mollis nunc. Dui sapien eget mi proin sed. Arcu odio ut sem nulla pharetra diam. Ipsum nunc aliquet bibendum enim. Tempor commodo ullamcorper a lacus vestibulum sed arcu non odio."
- Observe 431 status code returned instead of expected 200
Enabling Debug logging we can see following, at info level there are no logs printed
2023-08-05 12:09:22,541 DEBUG [reactor-http-nio-2] i.n.c.DefaultChannelPipeline: Discarded message pipeline : [reactor.left.httpCodec, reactor.left.h2MultiplexHandler, DefaultChannelPipeline$TailContext#0]. Channel : [id: 0x84aa76b7, L:/127.0.0.1:8080 - R:/127.0.0.1:55365].
2023-08-05 12:09:22,546 DEBUG [reactor-http-nio-2] i.n.u.i.l.AbstractInternalLogger: Stream exception thrown for unknown stream 1.
io.netty.handler.codec.http2.Http2Exception$HeaderListSizeException: Header size exceeded max allowed size (8192)
at io.netty.handler.codec.http2.Http2Exception.headerListSizeError(Http2Exception.java:195)
at io.netty.handler.codec.http2.Http2CodecUtil.headerListSizeExceeded(Http2CodecUtil.java:233)
at io.netty.handler.codec.http2.HpackDecoder$Http2HeadersSink.finish(HpackDecoder.java:543)
at io.netty.handler.codec.http2.HpackDecoder.decode(HpackDecoder.java:136)
at io.netty.handler.codec.http2.DefaultHttp2HeadersDecoder.decodeHeaders(DefaultHttp2HeadersDecoder.java:160)
at io.netty.handler.codec.http2.DefaultHttp2FrameReader$HeadersBlockBuilder.headers(DefaultHttp2FrameReader.java:733)
at io.netty.handler.codec.http2.DefaultHttp2FrameReader$2.processFragment(DefaultHttp2FrameReader.java:476)
at io.netty.handler.codec.http2.DefaultHttp2FrameReader.readHeadersFrame(DefaultHttp2FrameReader.java:484)
at io.netty.handler.codec.http2.DefaultHttp2FrameReader.processPayloadState(DefaultHttp2FrameReader.java:253)
at io.netty.handler.codec.http2.DefaultHttp2FrameReader.readFrame(DefaultHttp2FrameReader.java:159)
at io.netty.handler.codec.http2.DefaultHttp2ConnectionDecoder.decodeFrame(DefaultHttp2ConnectionDecoder.java:173)
at io.netty.handler.codec.http2.DecoratingHttp2ConnectionDecoder.decodeFrame(DecoratingHttp2ConnectionDecoder.java:63)
at io.netty.handler.codec.http2.Http2ConnectionHandler$FrameDecoder.decode(Http2ConnectionHandler.java:393)
at io.netty.handler.codec.http2.Http2ConnectionHandler.decode(Http2ConnectionHandler.java:453)
at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:529)
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:468)
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:290)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:440)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166)
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:788)
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:724)
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:650)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:562)
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997)
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.base/java.lang.Thread.run(Thread.java:833)
2023-08-05 12:09:22,554 DEBUG [reactor-http-nio-2] i.n.c.DefaultChannelPipeline: Discarded inbound message DefaultHttp2SettingsAckFrame that reached at the tail of the pipeline. Please check your pipeline configuration.
2023-08-05 12:09:22,554 DEBUG [reactor-http-nio-2] i.n.c.DefaultChannelPipeline: Discarded message pipeline : [reactor.left.httpCodec, reactor.left.h2MultiplexHandler, DefaultChannelPipeline$TailContext#0]. Channel : [id: 0x84aa76b7, L:/127.0.0.1:8080 - R:/127.0.0.1:55365].
Same curl will work if the curl request is done with http 1.1.
This can be fixed with a custom NettyCustomizer uncomment @Component to validate it fixes the problem. But this is unexpected behaviour as the max header size setting should apply regardless which http protocol is used. So I suggest to fix it in Spring boot with this PR.
Comment From: pivotal-cla
@NersesAM Please sign the Contributor License Agreement!
Click here to manually synchronize the status of this Pull Request.
See the FAQ for frequently asked questions.
Comment From: pivotal-cla
@NersesAM Thank you for signing the Contributor License Agreement!
Comment From: NersesAM
CONTRIBUTING file is not stating against which branch should I raise PR so I have chosen the current latest release branch. Do I need to create PRs against main, 3.0, 2.7(?) as well?
Comment From: scottfrederick
@NersesAM No need to create additional PRs. We can apply it to the appropriate branch once we've decided the earliest branch to apply the change to, then forward-merge to newer branches.
Comment From: mhalbritter
Thank you very much! I polished your changes in this commit: https://github.com/spring-projects/spring-boot/commit/dc62e5fbc35c860008e47394f53086e036b4566c