Backend API. Server-side code: this runs in a Codename One backend, not in the app on the device.
public final class Http2
- Object
- 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 types
class Http2.Stream | One request, once the client has finished sending it. |
Fields
public static final String ALPN = "h2" | The ALPN identifier. |
Methods
public static Http2 create()
throws IOException | A new server session, with the SETTINGS preface already queued. |
public void receive(byte[] buffer, int offset, int length)
throws IOException | Feeds received bytes to the session. |
public Http2.Stream nextRequest() | The next completed request, or null. |
public boolean respond(int streamId, int status, String contentType, List extraHeaders, byte[] body)
throws IOException |
|
public static void setMaxBodyBytes(long limit) | The ceiling for outstanding response bodies across the process. |
public static void setMaxFileBodies(int limit) | The ceiling for outstanding FILE-backed bodies across the process. |
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. |
public byte[] drain()
throws IOException | Runs the session’s output side and returns the bytes to put on the wire. |
public int[] closedStreams() | The streams that have closed since the last call, as (stream id, HTTP/2 error code) pairs; null when none have. |
public boolean isAlive() | False once the session is finished and the connection can be closed. |
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. |
public static int pendingBodyFiles() | File-backed response bodies outstanding across the PROCESS, not this session. |
public static long pendingBodyBytesAll() | Response-body heap outstanding across the PROCESS rather than this session. |
public void close() |
Inherited methods
Field details
ALPN
public static final String ALPN = "h2"Method details
create
public static Http2 create()
throws IOExceptionThrows
receive
public void receive(byte[] buffer, int offset, int length)
throws IOExceptionThrows
nextRequest
public Http2.Stream nextRequest()respond
public boolean respond(int streamId, int status, String contentType, List extraHeaders, byte[] body)
throws IOExceptionextraHeaders: “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
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 IOExceptionResponds 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
drain
public byte[] drain()
throws IOExceptionThrows
closedStreams
public int[] closedStreams()isAlive
public boolean isAlive()pendingBodyBytes
public long pendingBodyBytes()pendingBodyFiles
public static int pendingBodyFiles()pendingBodyBytesAll
public static long pendingBodyBytesAll()close
public void close()