Class Http2
One HTTP/2 connection, on nghttp2.
The framing is not implemented here and should not be: HPACK alone is a static table, a dynamic table with eviction and Huffman coding, and flow control, stream state, CONTINUATION reassembly and GOAWAY are all their own problems. nghttp2 owns those. This class owns the shape of the boundary.
Java PULLS from the session rather than being called back into. nghttp2 is callback-driven, but a C callback that reaches into the VM has to survive dead-code elimination and must not run while the collector is moving; the callbacks instead accumulate completed requests and this class takes them.
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic final classOne request, once the client has finished sending it. -
Field Summary
Fields -
Method Summary
Modifier and TypeMethodDescriptionvoidclose()int[]The streams that have closed since the last call, as (stream id, HTTP/2 error code) pairs; null when none have.static Http2create()A new server session, with the SETTINGS preface already queued.byte[]drain()Runs the session's output side and returns the bytes to put on the wire.booleanisAlive()False once the session is finished and the connection can be closed.The next completed request, or null.longHeap held by response bodies that have been submitted and not yet fully written, which is NOT what drain() empties: that buffer is what nghttp2 has already serialised.static longResponse-body heap outstanding across the PROCESS rather than this session.static intFile-backed response bodies outstanding across the PROCESS, not this session.voidreceive(byte[] buffer, int offset, int length) Feeds received bytes to the session.booleanextraHeaders: "name: value" strings.
booleanrespondFile(int streamId, int status, String contentType, List extraHeaders, int fd, long offset, long length) Responds with a range of an open file, without reading it into the heap.static voidsetMaxBodyBytes(long limit) The ceiling for outstanding response bodies across the process.static voidsetMaxFileBodies(int limit) The ceiling for outstanding FILE-backed bodies across the process.
-
Field Details
-
ALPN
The ALPN identifier. There is no upgrade handshake for h2 over TLS.- See Also:
-
-
Method Details
-
create
A new server session, with the SETTINGS preface already queued.- Throws:
IOException
-
receive
Feeds received bytes to the session.- Throws:
IOException
-
nextRequest
The next completed request, or null. A stream is complete only when END_STREAM arrives -- on the HEADERS frame for a request with no body, on the last DATA frame otherwise. -
respond
public boolean respond(int streamId, int status, String contentType, List extraHeaders, byte[] body) throws IOException extraHeaders: "name: value" strings. Connection-specific headers are dropped, because HTTP/2 forbids them, and names are lower-cased, because a capital letter is a protocol error the peer resets the stream over.
- Throws:
IOException
-
setMaxBodyBytes
public static void setMaxBodyBytes(long limit) The ceiling for outstanding response bodies across the process.
Set once, and enforced natively where the memory is actually taken.
-
setMaxFileBodies
public static void setMaxFileBodies(int limit) The ceiling for outstanding FILE-backed bodies across the process.
Enforced natively for the same reason as the byte ceiling: the slot has to be taken in the same step as the descriptor, or every worker finishing at once passes the check before any of them counts.
-
respondFile
public boolean respondFile(int streamId, int status, String contentType, List extraHeaders, int fd, long offset, long length) throws IOException Responds with a range of an open file, without reading it into the heap.
HTTP/2 cannot use sendfile -- the bytes have to become DATA frames -- but that is not a reason to materialise the whole file first. Reading it in cost the file's size in Java plus the same again in the native copy, so a large enough public file turned one request into an OutOfMemoryError, which the handler's
catch (Exception)does not catch. The provider reads each frame straight out of the descriptor instead, so the memory is one frame regardless of size, and nghttp2's flow control decides the pace.The descriptor is owned by the session from here: it is closed when the stream reaches EOF, when it is reset early, and when the session is torn down.
- Throws:
IOException
-
drain
Runs the session's output side and returns the bytes to put on the wire. Empty when there is nothing pending.- Throws:
IOException
-
closedStreams
public int[] closedStreams()The streams that have closed since the last call, as (stream id, HTTP/2 error code) pairs; null when none have. Code 0 is a stream whose response was sent in full; anything else is one reset before it was. A reset the PEER sent with NO_ERROR is reported as -1, not 0: it closes with code 0 too, and is no proof the response arrived. The server ends a request's span here, since a body the peer's flow-control window holds back is sent turns after it was submitted. -
isAlive
public boolean isAlive()False once the session is finished and the connection can be closed. -
pendingBodyBytes
public long pendingBodyBytes()Heap held by response bodies that have been submitted and not yet fully written, which is NOT what drain() empties: that buffer is what nghttp2 has already serialised. nghttp2 pulls from a submitted body only as the peer's flow-control window allows, so a client that stops sending WINDOW_UPDATE leaves every body it asked for sitting here. A caller that keeps submitting has to look at this figure rather than at what it just handed over, because a flush that could write nothing frees nothing. -
pendingBodyFiles
public static int pendingBodyFiles()File-backed response bodies outstanding across the PROCESS, not this session. Such a body holds a descriptor and no heap, so it is invisible to pendingBodyBytes, and descriptors are a process resource: bounding them per connection still multiplies by the connection count, and exhausting them stops the process opening sockets or files at all. -
pendingBodyBytesAll
public static long pendingBodyBytesAll()Response-body heap outstanding across the PROCESS rather than this session. The per-session figure says what one connection holds; a limit on that is a limit per connection, and the connection ceiling is in the thousands, so it bounds nothing about the machine. -
close
public void close()
-