velt/net/http/h2
import { FrameWriter, HpackDecoder, HpackEncoder, SETTINGS, … } from "velt/net/http/h2".
HTTP/2's wire format (RFC 9113) and HPACK (RFC 7541), written in Velt: what the
fetch client and HTTP/2 servers (the
HTTP server package is one) share. It works on
bytes (u8[] buffers and offsets) and leaves connections, streams and flow control to its
users.
- Frames. The frame types (
DATA,HEADERS,PRIORITY,RST_STREAM,SETTINGS,PUSH_PROMISE,PING,GOAWAY,WINDOW_UPDATE,CONTINUATION), the flags (END_STREAM,ACK,END_HEADERS,PADDED,PRIORITY_FLAG), the settings (SETTINGS_HEADER_TABLE_SIZE…SETTINGS_MAX_HEADER_LIST_SIZE, and RFC 8441'sSETTINGS_ENABLE_CONNECT_PROTOCOL) and the error codes (NO_ERROR…HTTP_1_1_REQUIRED;errorName(code)names one for messages), as numbers.HEADER_LENGTHis the 9-byte frame header;frameLength,readStreamIdandreadU32read its fields from a buffer. The limits:DEFAULT_WINDOW,MAX_WINDOW,MIN_MAX_FRAME_SIZE,MAX_MAX_FRAME_SIZE. - The preface.
isPreface(b, at)says whether the 24 bytes (PREFACE_LENGTH) atatare the client's connection preface;mayBePreface(b, at, end)whether fewer bytes may still become one (a server that also speaks HTTP/1.1 tells the two apart with it). FrameWriter: the frames a connection sends, encoded into one buffer that leaves in one write.- HPACK.
HpackEncoderencodes a connection's header blocks,HpackDecoderdecodes them into aFieldList(the fields as bytes and ranges, with no string made for a field nobody reads), each keeping the connection's dynamic table. The Huffman code ishuffmanEncode,huffmanDecodeandhuffmanLength.
A header block written by one side's encoder and read by the other's decoder:
ts
import {
FieldList,
FrameWriter,
frameLength,
HEADER_LENGTH,
HpackDecoder,
HpackEncoder,
END_STREAM,
MIN_MAX_FRAME_SIZE,
} from "velt/net/http/h2";
const out = new FrameWriter();
const enc = new HpackEncoder();
const at = out.beginHeaders();
enc.begin(out);
enc.status(out, 200);
enc.field(out, "content-type", "text/plain");
out.endHeaders(at, 1, END_STREAM, MIN_MAX_FRAME_SIZE);
const fields = new FieldList();
const end = HEADER_LENGTH + frameLength(out.buf, 0);
console.log(new HpackDecoder().decode(out.buf, HEADER_LENGTH, end, fields)); // true
console.log(fields.pairs()); // [ [ ':status', '200' ], [ 'content-type', 'text/plain' ] ]