Class Http3ConnectUdpHandler

java.lang.Object
io.netty.channel.ChannelHandlerAdapter
io.netty.channel.ChannelInboundHandlerAdapter
org.mockserver.netty.http3.Http3ConnectUdpHandler
All Implemented Interfaces:
io.netty.channel.ChannelHandler, io.netty.channel.ChannelInboundHandler

public class Http3ConnectUdpHandler extends io.netty.channel.ChannelInboundHandlerAdapter
HTTP/3 CONNECT-UDP (MASQUE, RFC 9298) relay handler.

This handler intercepts HTTP/3 extended CONNECT requests with :protocol = connect-udp when the http3ConnectUdpEnabled configuration flag is set to true. It is inserted into the QUIC stream pipeline before the regular Http3MockServerHandler so that CONNECT-UDP requests are handled here and non-CONNECT requests pass through to the normal mock pipeline.

Relay design:

  1. The handler recognises an extended CONNECT request by checking :method = CONNECT and :protocol = connect-udp.
  2. The target authority is parsed from the :authority pseudo-header (host:port).
  3. A UDP NioDatagramChannel is opened and connected to the target address.
  4. The handler responds with 200 OK to indicate the tunnel is established.
  5. Subsequent HTTP/3 DATA frames received on the QUIC stream are forwarded as UDP datagrams to the target. Each DATA frame payload is sent as one UDP datagram (simple 1:1 mapping without capsule framing -- suitable for testing).
  6. UDP datagrams received from the target are forwarded back to the client as HTTP/3 DATA frames on the same QUIC stream.
  7. When the QUIC stream is closed (input closed, error, or handler removal), the UDP channel is closed to release resources.

Plain CONNECT requests (without :protocol) are passed through to the next handler in the pipeline (the mock handler) -- MockServer is not a TCP forward proxy.

Framing note: a production MASQUE proxy would use the HTTP Datagram / Capsule Protocol (RFC 9297) framing. This implementation uses a simplified 1:1 DATA-frame-to-UDP-datagram mapping which is sufficient for testing and mock-server usage. The Capsule Protocol adds a context ID varint prefix; clients that require it should be adapted accordingly.

See Also:
  • Nested Class Summary

    Nested classes/interfaces inherited from interface io.netty.channel.ChannelHandler

    io.netty.channel.ChannelHandler.Sharable
  • Constructor Summary

    Constructors
    Constructor
    Description
     
  • Method Summary

    Modifier and Type
    Method
    Description
    void
    channelInactive(io.netty.channel.ChannelHandlerContext ctx)
     
    void
    channelRead(io.netty.channel.ChannelHandlerContext ctx, Object msg)
     
    void
    exceptionCaught(io.netty.channel.ChannelHandlerContext ctx, Throwable cause)
     
    void
    handlerRemoved(io.netty.channel.ChannelHandlerContext ctx)
     

    Methods inherited from class io.netty.channel.ChannelInboundHandlerAdapter

    channelActive, channelReadComplete, channelRegistered, channelUnregistered, channelWritabilityChanged, userEventTriggered

    Methods inherited from class io.netty.channel.ChannelHandlerAdapter

    ensureNotSharable, handlerAdded, isSharable

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

    Methods inherited from interface io.netty.channel.ChannelHandler

    handlerAdded
  • Constructor Details

    • Http3ConnectUdpHandler

      public Http3ConnectUdpHandler()
  • Method Details

    • channelRead

      public void channelRead(io.netty.channel.ChannelHandlerContext ctx, Object msg) throws Exception
      Specified by:
      channelRead in interface io.netty.channel.ChannelInboundHandler
      Overrides:
      channelRead in class io.netty.channel.ChannelInboundHandlerAdapter
      Throws:
      Exception
    • channelInactive

      public void channelInactive(io.netty.channel.ChannelHandlerContext ctx) throws Exception
      Specified by:
      channelInactive in interface io.netty.channel.ChannelInboundHandler
      Overrides:
      channelInactive in class io.netty.channel.ChannelInboundHandlerAdapter
      Throws:
      Exception
    • handlerRemoved

      public void handlerRemoved(io.netty.channel.ChannelHandlerContext ctx) throws Exception
      Specified by:
      handlerRemoved in interface io.netty.channel.ChannelHandler
      Overrides:
      handlerRemoved in class io.netty.channel.ChannelHandlerAdapter
      Throws:
      Exception
    • exceptionCaught

      public void exceptionCaught(io.netty.channel.ChannelHandlerContext ctx, Throwable cause)
      Specified by:
      exceptionCaught in interface io.netty.channel.ChannelHandler
      Specified by:
      exceptionCaught in interface io.netty.channel.ChannelInboundHandler
      Overrides:
      exceptionCaught in class io.netty.channel.ChannelInboundHandlerAdapter