Class LoopbackHttp2StreamErrorHandler

java.lang.Object
io.netty.channel.ChannelHandlerAdapter
io.netty.channel.ChannelInboundHandlerAdapter
org.mockserver.netty.proxy.relay.LoopbackHttp2StreamErrorHandler
All Implemented Interfaces:
io.netty.channel.ChannelHandler, io.netty.channel.ChannelInboundHandler

public class LoopbackHttp2StreamErrorHandler extends io.netty.channel.ChannelInboundHandlerAdapter
Answers the proxy client's HTTP/2 stream when the CONNECT/SOCKS relay's HTTP/2 loopback stream for it ends without a response: the response failed to decode, passed maxRequestBodySize, or MockServer reset the stream. The loopback stream ids are not the client's (LoopbackHttp2StreamIdRemapper pairs them), so the client stream paired with the loopback stream is reset, and the other streams on both connections carry on.
  • MockServer reset the loopback stream: the client's stream is reset with the same error code;
  • the request never reached MockServer (its HEADERS were not sent, or a GOAWAY says it was not processed): REFUSED_STREAM, which tells the client it may safely retry (RFC 9113 section 8.7);
  • otherwise, a failure in the relay itself: INTERNAL_ERROR.
A stream whose whole final response has been relayed is answered (LoopbackHttp2StreamIdRemapper.answered(int)), so its close is not reset. A client stream that ends without one is unpaired, then reset on the loopback so MockServer stops working on it (proxyClientFrameListener(io.netty.handler.codec.http2.Http2Connection, io.netty.handler.codec.http2.Http2FrameListener)): with the client's code when the client reset it, with CANCEL when the relay did (a stream error in the client's request). A loopback connection that closes outright is left to LoopbackHttp2ConnectionCloseHandler, which answers every client stream still open. Sits after the loopback's Http2ConnectionHandler, on either side of the LoopbackHttp2StreamIdRemapper: it reads no message, only the two connections' stream events; one per loopback. It calls the other channel's Http2ConnectionHandler directly, which is safe only because the loopback is bootstrapped on the proxy client's event loop (RelayConnectHandler.channelRead0).
  • Nested Class Summary

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

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

    Constructors
    Constructor
    Description
    LoopbackHttp2StreamErrorHandler(org.mockserver.logging.MockServerLogger mockServerLogger, io.netty.handler.codec.http2.Http2Connection loopbackConnection, LoopbackHttp2StreamIdRemapper streamIds, io.netty.channel.Channel proxyClientChannel)
     
  • Method Summary

    Modifier and Type
    Method
    Description
    io.netty.handler.codec.http2.Http2FrameListener
    frameListener(io.netty.handler.codec.http2.Http2FrameListener delegate)
    Wraps the loopback's frame listener to record why a stream is about to be reset.
    void
    handlerAdded(io.netty.channel.ChannelHandlerContext ctx)
     
    io.netty.handler.codec.http2.Http2FrameListener
    proxyClientFrameListener(io.netty.handler.codec.http2.Http2Connection proxyClientConnection, io.netty.handler.codec.http2.Http2FrameListener delegate)
    Wraps the proxy client's frame listener, and listens to its connection, so a client stream that ends without a whole response is reset on the loopback too, and the client's other streams carry on.

    Methods inherited from class io.netty.channel.ChannelInboundHandlerAdapter

    channelActive, channelInactive, channelRead, channelReadComplete, channelRegistered, channelUnregistered, channelWritabilityChanged, exceptionCaught, userEventTriggered

    Methods inherited from class io.netty.channel.ChannelHandlerAdapter

    ensureNotSharable, handlerRemoved, 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

    handlerRemoved
  • Constructor Details

    • LoopbackHttp2StreamErrorHandler

      public LoopbackHttp2StreamErrorHandler(org.mockserver.logging.MockServerLogger mockServerLogger, io.netty.handler.codec.http2.Http2Connection loopbackConnection, LoopbackHttp2StreamIdRemapper streamIds, io.netty.channel.Channel proxyClientChannel)
  • Method Details

    • frameListener

      public io.netty.handler.codec.http2.Http2FrameListener frameListener(io.netty.handler.codec.http2.Http2FrameListener delegate)
      Wraps the loopback's frame listener to record why a stream is about to be reset.
    • proxyClientFrameListener

      public io.netty.handler.codec.http2.Http2FrameListener proxyClientFrameListener(io.netty.handler.codec.http2.Http2Connection proxyClientConnection, io.netty.handler.codec.http2.Http2FrameListener delegate)
      Wraps the proxy client's frame listener, and listens to its connection, so a client stream that ends without a whole response is reset on the loopback too, and the client's other streams carry on. A reset the client sends is relayed with its code; a stream the relay resets itself never reaches the frame listener, so its close is what resets the loopback stream.
    • handlerAdded

      public void handlerAdded(io.netty.channel.ChannelHandlerContext ctx)
      Specified by:
      handlerAdded in interface io.netty.channel.ChannelHandler
      Overrides:
      handlerAdded in class io.netty.channel.ChannelHandlerAdapter