Class LenientInboundHttp2StreamFrameCodec

java.lang.Object
io.netty.channel.ChannelHandlerAdapter
io.netty.channel.ChannelInboundHandlerAdapter
io.netty.channel.ChannelDuplexHandler
io.netty.handler.codec.MessageToMessageCodec<io.netty.handler.codec.http2.Http2StreamFrame,io.netty.handler.codec.http.HttpObject>
io.netty.handler.codec.http2.Http2StreamFrameToHttpObjectCodec
org.mockserver.netty.unification.LenientInboundHttp2StreamFrameCodec
All Implemented Interfaces:
io.netty.channel.ChannelHandler, io.netty.channel.ChannelInboundHandler, io.netty.channel.ChannelOutboundHandler

public class LenientInboundHttp2StreamFrameCodec extends io.netty.handler.codec.http2.Http2StreamFrameToHttpObjectCodec
A Http2StreamFrameToHttpObjectCodec that is lenient on the INBOUND (request) side but strict on the OUTBOUND (response) side.

Netty's Http2StreamFrameToHttpObjectCodec carries a single validateHeaders flag that governs both directions of the HTTP/1-object ↔ HTTP/2-frame conversion. On the gRPC multiplex re-aggregating chain MockServer needs the two directions to differ:

  • Inbound (lenient, validateHeaders=false): a request header value with a leading space, an embedded 0x7F (DEL), or a control character must be accepted and reach the matchers rather than being rejected with RST_STREAM(PROTOCOL_ERROR) before matching. This mirrors the shared-connection path, which sets InboundHttp2ToHttpAdapterBuilder.validateHttpHeaders(false). The base class applies this flag in decode/newMessage/newFullMessage via HttpConversionUtil.toHttpRequest(int, io.netty.handler.codec.http2.Http2Headers, boolean)/toFullHttpRequest.
  • Outbound (strict): response header NAMES and trailer NAMES must still be validated exactly as Netty validates them by default, matching the shared-connection path whose AbstractHttp2ConnectionHandlerBuilder.isValidateHeaders() defaults to true. Passing false to the base class also silently relaxed this outbound name validation, which this subclass restores.

Only header/trailer NAMES are validated outbound — never values. The base class builds outbound headers with HttpConversionUtil.toHttp2Headers(..., validateHeaders), which uses the 2-arg DefaultHttp2Headers(validate, arraySizeHint) constructor: that installs a name validator (HTTP2_NAME_VALIDATOR) when validate is true and no value validator either way. (The separate 3-arg DefaultHttp2Headers(validate, validateValues, arraySizeHint) constructor can install a value validator, but the codec does not use it.) Header names are also lower-cased before validation, so an uppercase name never trips it — only an illegal token character (space, control char, DEL, separator, non-ASCII) does.

How the strict outbound check is re-asserted: rather than re-implementing the RFC token rule by hand (which would drift from Netty across upgrades), this override performs the exact conversion the base class would have performed with validation on — toHttp2Headers(msg, true) for a response head and toHttp2Headers(trailingHeaders, true) for non-empty trailers — and discards the result, letting it throw exactly the Http2Exception the strict path would throw. The subsequent super.encode then re-does the conversion with validateHeaders=false; this is one extra header conversion per response head (and per trailer block), a deliberate and acceptable cost to keep the check faithful to Netty. Per-chunk HttpContent carries no headers and is not validated.

  • 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
    protected void
    encode(io.netty.channel.ChannelHandlerContext ctx, io.netty.handler.codec.http.HttpObject obj, List<Object> out)
     

    Methods inherited from class io.netty.handler.codec.http2.Http2StreamFrameToHttpObjectCodec

    acceptInboundMessage, decode, handlerAdded, isSsl

    Methods inherited from class io.netty.handler.codec.MessageToMessageCodec

    acceptOutboundMessage, channelRead, channelReadComplete, write

    Methods inherited from class io.netty.channel.ChannelDuplexHandler

    bind, close, connect, deregister, disconnect, flush, read

    Methods inherited from class io.netty.channel.ChannelInboundHandlerAdapter

    channelActive, channelInactive, 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

    • LenientInboundHttp2StreamFrameCodec

      public LenientInboundHttp2StreamFrameCodec()
  • Method Details

    • encode

      protected void encode(io.netty.channel.ChannelHandlerContext ctx, io.netty.handler.codec.http.HttpObject obj, List<Object> out) throws Exception
      Overrides:
      encode in class io.netty.handler.codec.http2.Http2StreamFrameToHttpObjectCodec
      Throws:
      Exception