Class Http3FramePipeline

java.lang.Object
org.microproxy.frames.Http3FramePipeline

public final class Http3FramePipeline extends Object
Runs a FrameInterceptor over HTTP/3 traffic given as the bytes of its streams: it reads frames from a request stream or a control stream, shows each to the interceptor as an Http3Frame (HEADERS decoded through QPACK), and writes what comes back to an output stream.

Where the proxy speaks HTTP/3 itself (a reverse proxy's HTTP/3 listener, connections to HTTP/3 servers), the interceptor configured with HttpProxyServerBootstrap.withFrameInterceptor(org.microproxy.frames.FrameInterceptor) sees those frames live, under the same rules; this pipeline processes HTTP/3 streams captured or relayed by other means. It needs the optional http3-codec module on the class path (available()).


 Http3FramePipeline pipeline = Http3FramePipeline.builder(interceptor)
         .direction(FrameDirection.FROM_CLIENT)   // whose frames these are
         .build();
 pipeline.controlStream(2, clientControlIn, controlOut);    // stream type, SETTINGS, ...
 pipeline.encoderStream(clientQpackEncoderIn);              // only if the client's QPACK uses a dynamic table
 pipeline.requestStream(0, requestStreamIn, requestOut);    // HEADERS, DATA, trailers
 

A pipeline stands for one sender's streams on one connection: it keeps that sender's QPACK decoder, so feed it the sender's QPACK encoder stream (encoderStream(java.io.InputStream)) when its field sections use the dynamic table, before the request streams that need it. Field sections are written back with static-only QPACK, which never needs an encoder stream. Its methods may run on several threads at once, one stream each.

The rules are FrameInterceptor's, adapted to HTTP/3, whose frames carry no stream id and no END_STREAM (a message ends with its stream). Live, received SETTINGS may only become stricter and sent SETTINGS may change only in extension settings, as for HTTP/2; DATA may be edited to any size, and QUIC's flow control counts what is on the wire; field sections are encoded through the connection's QPACK encoder:

Allowed results per HTTP/3 frame type
FrameMay be editedMay be droppedMay be followed by
DATAthe payloadyesDATA; HEADERS (trailers); extension frames
HEADERSthe fieldsnoHEADERS; extension frames
SETTINGSthe values (valid HTTP/3 settings)noextension frames
extension and reserved (grease) frameseverythingyesextension frames
GOAWAY, MAX_PUSH_ID, CANCEL_PUSH, PUSH_PROMISEnothingnonothing

Header fields must pass Field.validate(java.util.List<org.microproxy.frames.Field>), and frames must keep the stream's order: a request or response is HEADERS (after interim 1xx HEADERS, for a response), DATA, then optional trailing HEADERS. A result that breaks a rule is logged and the original frame written instead; so is a frame whose interceptor throws. If an earlier result ended the message (by adding trailers) and the input goes on with DATA, the stream fails with H3_FRAME_UNEXPECTED. Input that breaks HTTP/3 fails with an IOException (the codec's Http3Exception), after the frames before it were written.

  • Nested Class Summary

    Nested Classes
    Modifier and Type
    Class
    Description
    static final class 
    Options for Http3FramePipeline.
  • Method Summary

    Modifier and Type
    Method
    Description
    static boolean
    Whether the optional http3-codec module is on the class path, so that a pipeline can be built.
    Starts a pipeline that shows frames to interceptor.
    void
    controlStream(long streamId, InputStream in, OutputStream out)
    Processes a control stream, from its stream type (which must be 0x00, the control stream's) until its end, writing the result, stream type first, to out, which is flushed after each frame and not closed.
    void
    Reads the sender's QPACK encoder stream, from its stream type (0x02) until its end, so that field sections that use the dynamic table can be decoded.
    void
    requestStream(long streamId, InputStream in, OutputStream out)
    Processes a request stream (a bidirectional stream: a request from a client, or the response to it from a server) until its end, writing the result to out, which is flushed after each frame and not closed.

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Method Details

    • available

      public static boolean available()
      Whether the optional http3-codec module is on the class path, so that a pipeline can be built.
      Returns:
      whether the codec is present
    • builder

      public static Http3FramePipeline.Builder builder(FrameInterceptor interceptor)
      Starts a pipeline that shows frames to interceptor.
      Parameters:
      interceptor - the interceptor
      Returns:
      a builder
    • requestStream

      public void requestStream(long streamId, InputStream in, OutputStream out) throws IOException
      Processes a request stream (a bidirectional stream: a request from a client, or the response to it from a server) until its end, writing the result to out, which is flushed after each frame and not closed.
      Parameters:
      streamId - the QUIC stream id, 0 or more (FrameContext.streamId())
      in - the stream's bytes
      out - where the stream's new bytes go
      Throws:
      IOException - if reading or writing fails, or the input breaks HTTP/3
    • controlStream

      public void controlStream(long streamId, InputStream in, OutputStream out) throws IOException
      Processes a control stream, from its stream type (which must be 0x00, the control stream's) until its end, writing the result, stream type first, to out, which is flushed after each frame and not closed.
      Parameters:
      streamId - the QUIC stream id (FrameContext.streamId()), or -1 if unknown
      in - the stream's bytes
      out - where the stream's new bytes go
      Throws:
      IOException - if reading or writing fails, or the input breaks HTTP/3
    • encoderStream

      public void encoderStream(InputStream in) throws IOException
      Reads the sender's QPACK encoder stream, from its stream type (0x02) until its end, so that field sections that use the dynamic table can be decoded. Feed it before the request streams whose sections need its instructions; a section that needs instructions not given yet fails its stream.
      Parameters:
      in - the encoder stream's bytes
      Throws:
      IOException - if reading fails, or the stream is not a valid QPACK encoder stream