Skip to content
Standard library

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's SETTINGS_ENABLE_CONNECT_PROTOCOL) and the error codes (NO_ERROR … HTTP_1_1_REQUIRED; errorName(code) names one for messages), as numbers. HEADER_LENGTH is the 9-byte frame header; frameLength, readStreamId and readU32 read 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) at at are 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. HpackEncoder encodes a connection's header blocks, HpackDecoder decodes them into a FieldList (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 is huffmanEncode, huffmanDecode and huffmanLength.

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' ] ]

Edit this page on GitHub