Class Http3RequestBridge

java.lang.Object
org.mockserver.netty.http3.Http3RequestBridge

public final class Http3RequestBridge extends Object
Converts between HTTP/3 frames and MockServer's HttpRequest/HttpResponse model.

These are pure conversion helpers with no Netty channel dependencies, so they can be unit-tested without the native QUIC transport.

  • Method Details

    • toHttpRequest

      public static org.mockserver.model.HttpRequest toHttpRequest(String method, String path, String scheme, String authority, List<Map.Entry<String,String>> headers, byte[] body)
      Build a MockServer HttpRequest from the HTTP/3 pseudo-headers and accumulated body bytes.
      Parameters:
      method - the :method pseudo-header value
      path - the :path pseudo-header value (may include query string)
      scheme - the :scheme pseudo-header value (nullable)
      authority - the :authority pseudo-header value (nullable)
      headers - list of non-pseudo-header name/value pairs
      body - the accumulated request body bytes (may be empty)
      Returns:
      a fully populated HttpRequest
    • toHttpRequest

      public static org.mockserver.model.HttpRequest toHttpRequest(String method, String path, String scheme, String authority, List<Map.Entry<String,String>> headers, io.netty.buffer.ByteBuf body)
      As toHttpRequest(String, String, String, String, List, byte[]), but reads the accumulated request body from the ByteBuf it was accumulated into, copying it once.

      The body is decoded by BodyDecoderEncoder.bytesToBody(byte[], java.lang.String), exactly as the HTTP/1.1 and HTTP/2 mappers do, so it keeps the wire bytes as its raw bytes and gets the same body type and charset for every Content-Type.

      Buffer ownership: the body is read non-destructively (reader index is not advanced) and the buffer is not released here — the caller retains ownership and must release it (the production handler does so in a finally, on every path including errors).

    • toHttpRequest

      public static org.mockserver.model.HttpRequest toHttpRequest(String method, String path, String scheme, String authority, List<Map.Entry<String,String>> headers, io.netty.buffer.ByteBuf body, io.netty.buffer.ByteBuf decompressedBody)
      As toHttpRequest(String, String, String, String, List, ByteBuf), unless decompressedBody (the body Http3RequestDecompressor decompressed) is non-null: the request is then the one HTTP/1.1's decompressor, aggregator and request mapper build. The body is the decompressed bytes and the wire bytes are kept as its original body (when they differ); a content-length is replaced by the decompressed size, and content-encoding is kept but moved after the other headers. Neither buffer is released here.
    • parseHeaders

      public static Http3RequestBridge.ParsedHeaders parseHeaders(io.netty.handler.codec.http3.Http3HeadersFrame headersFrame)
      Extract pseudo-headers and regular headers from an HTTP/3 headers frame.
    • toHttp3HeadersFrame

      public static io.netty.handler.codec.http3.DefaultHttp3HeadersFrame toHttp3HeadersFrame(org.mockserver.model.HttpResponse response)
      Convert a MockServer HttpResponse into an HTTP/3 headers frame.
    • toHttp3HeadersFrame

      public static io.netty.handler.codec.http3.DefaultHttp3HeadersFrame toHttp3HeadersFrame(org.mockserver.model.HttpResponse response, boolean streaming)
      As toHttp3HeadersFrame(HttpResponse), additionally dropping content-length when streaming is true. A streamed response's length is not known when the headers are sent, and a content-length copied from (for example) a relayed upstream response describes a different body than the one actually streamed - which a conforming client treats as a malformed message rather than merely ignoring.
    • toHttp3TrailersFrame

      public static io.netty.handler.codec.http3.DefaultHttp3HeadersFrame toHttp3TrailersFrame(org.mockserver.model.HttpResponse response)
      Build a trailing HTTP/3 HEADERS frame from the response trailers, or null when the response carries no trailers. The trailer field names are lower-cased per HTTP/3 (HTTP/2-style) header conventions. This is the general-purpose (non-gRPC) trailer frame; gRPC trailers (grpc-status / grpc-message) are emitted separately by Http3GrpcResponseWriter.
    • toHttp3DataFrame

      public static io.netty.handler.codec.http3.DefaultHttp3DataFrame toHttp3DataFrame(org.mockserver.model.HttpResponse response)
      Convert the body of a MockServer HttpResponse into an HTTP/3 data frame. Returns null if the response has no body.
    • accumulateBody

      public static void accumulateBody(io.netty.buffer.CompositeByteBuf composite, io.netty.handler.codec.http3.Http3DataFrame dataFrame)
      Accumulate body data from an HTTP/3 data frame into a composite buffer. HTTP/3 hands a body over in pieces of about one QUIC packet (1.1 KiB) whatever DATA frame size the client sent, so once the body has 64 components, pieces under 16 KiB are copied into 16 KiB blocks rather than kept one component each: each byte is copied at most once, and a body of one-byte pieces needs one component per 16 KiB.
    • limitComponents

      public static int limitComponents(io.netty.buffer.CompositeByteBuf composite, int componentLimit, int merged)
      Keeps composite under componentLimit components when accumulateBody(io.netty.buffer.CompositeByteBuf, io.netty.handler.codec.http3.Http3DataFrame) alone does not, which takes pieces alternating between small and 16 KiB or more. CompositeByteBuf's own consolidation copies the whole body each time; this copies only the components after the leading merged ones into one. The whole-body copy once half the limit is merged blocks needs a component limit far smaller than the body bound it is derived from, which maxRequestBodySize cannot produce.
      Returns:
      how many leading components are now merged blocks, to pass back on the next call
    • readAccumulatedBody

      public static byte[] readAccumulatedBody(io.netty.buffer.CompositeByteBuf composite)
      Read the accumulated composite buffer into a byte array.