You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When I connect to the Example server Http3ServerExample using Angie HTTP/3 proxy, request is forwarded to the server properly with its basic configuration. But if the proxy is configured to add Host header field in the request,
the HTTP/3 server fails to handle the request. Following is the exception I observed on the server side.
15:05:24.488 [nioEventLoopGroup-2-1] WARN io.netty.channel.DefaultChannelPipeline -- An exceptionCaught() event was fired, and it reached at the tail of the pipeline. It usually means the last handler in the pipeline did not handle the exception.
io.netty.incubator.codec.http3.Http3HeadersValidationException: Not all mandatory pseudo-headers included.
at io.netty.incubator.codec.http3.Http3HeadersSink.finish(Http3HeadersSink.java:109)
at io.netty.incubator.codec.http3.Http3FrameCodec.decodeHeaders(Http3FrameCodec.java:403)
at io.netty.incubator.codec.http3.Http3FrameCodec.decodeFrame(Http3FrameCodec.java:252)
at io.netty.incubator.codec.http3.Http3FrameCodec.decode(Http3FrameCodec.java:201)
at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:530)
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:469)
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:290)
at io.netty.incubator.codec.http3.Http3FrameCodec.channelRead(Http3FrameCodec.java:131)
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.incubator.codec.quic.QuicheQuicStreamChannel$QuicStreamChannelUnsafe.recv(QuicheQuicStreamChannel.java:978)
at io.netty.incubator.codec.quic.QuicheQuicStreamChannel$QuicStreamChannelUnsafe.beginRead(QuicheQuicStreamChannel.java:623)
at io.netty.channel.DefaultChannelPipeline$HeadContext.read(DefaultChannelPipeline.java:1362)
at io.netty.channel.AbstractChannelHandlerContext.invokeRead(AbstractChannelHandlerContext.java:845)
at io.netty.channel.AbstractChannelHandlerContext.read(AbstractChannelHandlerContext.java:824)
at io.netty.incubator.codec.http3.Http3FrameCodec.read(Http3FrameCodec.java:635)
at io.netty.channel.AbstractChannelHandlerContext.invokeRead(AbstractChannelHandlerContext.java:851)
at io.netty.channel.AbstractChannelHandlerContext.read(AbstractChannelHandlerContext.java:824)
at io.netty.incubator.codec.http3.Http3FrameTypeDuplexValidationHandler.read(Http3FrameTypeDuplexValidationHandler.java:85)
at io.netty.channel.AbstractChannelHandlerContext.invokeRead(AbstractChannelHandlerContext.java:851)
at io.netty.channel.AbstractChannelHandlerContext.read(AbstractChannelHandlerContext.java:824)
at io.netty.channel.DefaultChannelPipeline.read(DefaultChannelPipeline.java:1004)
at io.netty.channel.DefaultChannelPipeline.read(DefaultChannelPipeline.java:46)
at io.netty.incubator.codec.quic.QuicheQuicStreamChannel.read(QuicheQuicStreamChannel.java:288)
at io.netty.incubator.codec.quic.QuicheQuicStreamChannel.read(QuicheQuicStreamChannel.java:52)
at io.netty.channel.DefaultChannelPipeline$HeadContext.readIfIsAutoRead(DefaultChannelPipeline.java:1422)
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelActive(DefaultChannelPipeline.java:1400)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelActive(AbstractChannelHandlerContext.java:258)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelActive(AbstractChannelHandlerContext.java:238)
at io.netty.channel.DefaultChannelPipeline.fireChannelActive(DefaultChannelPipeline.java:895)
at io.netty.incubator.codec.quic.QuicheQuicStreamChannel$QuicStreamChannelUnsafe.register(QuicheQuicStreamChannel.java:488)
at io.netty.channel.SingleThreadEventLoop.register(SingleThreadEventLoop.java:89)
at io.netty.channel.SingleThreadEventLoop.register(SingleThreadEventLoop.java:83)
at io.netty.incubator.codec.quic.QuicheQuicChannel$1.onUnhandledInboundMessage(QuicheQuicChannel.java:435)
at io.netty.channel.DefaultChannelPipeline$TailContext.channelRead(DefaultChannelPipeline.java:1296)
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.incubator.codec.http3.Http3ConnectionHandler.channelRead(Http3ConnectionHandler.java:180)
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.incubator.codec.quic.QuicheQuicChannel$QuicChannelUnsafe.recvStream(QuicheQuicChannel.java:1808)
at io.netty.incubator.codec.quic.QuicheQuicChannel$QuicChannelUnsafe.processReceived(QuicheQuicChannel.java:1687)
at io.netty.incubator.codec.quic.QuicheQuicChannel$QuicChannelUnsafe.connectionRecv(QuicheQuicChannel.java:1622)
at io.netty.incubator.codec.quic.QuicheQuicChannel.recv(QuicheQuicChannel.java:942)
at io.netty.incubator.codec.quic.QuicheQuicCodec$QuicCodecHeaderProcessor.process(QuicheQuicCodec.java:375)
at io.netty.incubator.codec.quic.QuicHeaderParser.parse(QuicHeaderParser.java:130)
at io.netty.incubator.codec.quic.QuicheQuicCodec.handleQuicPacket(QuicheQuicCodec.java:204)
at io.netty.incubator.codec.quic.QuicheQuicCodec.channelRead(QuicheQuicCodec.java:195)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:442)
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.AbstractNioMessageChannel$NioMessageUnsafe.read(AbstractNioMessageChannel.java:97)
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:829)
The problem is that Angie omits :authority header field in the request when the proxy is configured to add Host header field. The request header field checker in Http3HeadersSink class does not recognize the host header field.
Here is the header fields sent when the connection was successful:
According to Section 7.2 of RFC 9110, :authority header field is not necessary when Host header field exists. So the behavior in the Angie should be legitimate.
I have a fix for this issue in my fork, shall I send a pull request?
When I connect to the Example server
Http3ServerExample
using Angie HTTP/3 proxy, request is forwarded to the server properly with its basic configuration. But if the proxy is configured to addHost
header field in the request,the HTTP/3 server fails to handle the request. Following is the exception I observed on the server side.
The problem is that Angie omits
:authority
header field in the request when the proxy is configured to addHost
header field. The request header field checker inHttp3HeadersSink
class does not recognize the host header field.Here is the header fields sent when the connection was successful:
Connection fails when the proxy sends following header fields:
According to Section 7.2 of RFC 9110,
:authority
header field is not necessary whenHost
header field exists. So the behavior in the Angie should be legitimate.I have a fix for this issue in my fork, shall I send a pull request?
In order to try running the Angie HTTP/3 proxy, I wrote a note how to set it up https://gist.github.com/naokiiwakami/bbd9788ee33a730cad56f23c041d4b4f
Following is the http server configuration in Angie when the connection is successful
Following is the configuration for the failed case. Directive
proxy_set_header
is added.The text was updated successfully, but these errors were encountered: