Class Http3FramePipeline
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:
| Frame | May be edited | May be dropped | May be followed by |
|---|---|---|---|
| DATA | the payload | yes | DATA; HEADERS (trailers); extension frames |
| HEADERS | the fields | no | HEADERS; extension frames |
| SETTINGS | the values (valid HTTP/3 settings) | no | extension frames |
| extension and reserved (grease) frames | everything | yes | extension frames |
| GOAWAY, MAX_PUSH_ID, CANCEL_PUSH, PUSH_PROMISE | nothing | no | nothing |
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 -
Method Summary
Modifier and TypeMethodDescriptionstatic booleanWhether the optionalhttp3-codecmodule is on the class path, so that a pipeline can be built.static Http3FramePipeline.Builderbuilder(FrameInterceptor interceptor) Starts a pipeline that shows frames tointerceptor.voidcontrolStream(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, toout, which is flushed after each frame and not closed.voidReads 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.voidrequestStream(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 toout, which is flushed after each frame and not closed.
-
Method Details
-
available
public static boolean available()Whether the optionalhttp3-codecmodule is on the class path, so that a pipeline can be built.- Returns:
- whether the codec is present
-
builder
Starts a pipeline that shows frames tointerceptor.- Parameters:
interceptor- the interceptor- Returns:
- a builder
-
requestStream
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 toout, which is flushed after each frame and not closed.- Parameters:
streamId- the QUIC stream id, 0 or more (FrameContext.streamId())in- the stream's bytesout- where the stream's new bytes go- Throws:
IOException- if reading or writing fails, or the input breaks HTTP/3
-
controlStream
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, toout, which is flushed after each frame and not closed.- Parameters:
streamId- the QUIC stream id (FrameContext.streamId()), or -1 if unknownin- the stream's bytesout- where the stream's new bytes go- Throws:
IOException- if reading or writing fails, or the input breaks HTTP/3
-
encoderStream
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
-