http leaf bindingAn HTTP server in lite (LITE-034) has its transport already — net.c is a Node-style async API over the pol loop, net.createServer accepts and streams. What is missing is message parsing: dog/abc/HTTP.h carries the ragel lexer (HTTP.c.rl → HTTP.rl.c) but no JS binding exposes it, and manual parsing in JS would be a second recognizer next to a working ragel one. This ticket adds the binding, leaf-only in the net.c/io.c style: C parses bytes and hands back slices, no JS state held, no protocol logic — keep-alive, routing and body handling stay in the JS bundle.
dog/abc/HTTP.h: HTTPstate carries data, the request line (method, uri, version), the status line (status_code, reason) and headers (a u8cssp name/value pair list); errors are HTTPFAIL/HTTPBAD/HTTPNONE.
HTTPutf8Drain(from, http) lexes one message head off a byte slice; HTTPutf8Feed(into, http) spells one back; HTTPfind(value, key, headers) looks a header up.quickjab/net.c + pol.c: JABC rule #4, C keeps no per-fd JS closures; leaves return bare values, buffers and dispatch live in the embedded JS bundle.quickjab/test/net.js), driven by the one implicit pol loop.JS can parse an HTTP message head from a Uint8Array and compose one, through the ragel lexer only.
HTTPutf8Feed, so responses are spelled by the same module that parses.HTTPNONE) surfaces as "need more bytes", never a throw — mirrors net.c's EAGAIN-as--1 stance.net + the new leaves.HTTPLexer/HTTPutf8Drain; JS never scans header bytes itself.abc/INDEX.md + dog/INDEX.md before adding anything; update the index if a header is touched.http._drain, http._feed?) to be shown to gritzko before code — API freeze rule applies.Built in //QJAB-004 (///quickjab#61895a7f), not committed.
http._drain(Uint8Array) → null | {method, uri, version, status,
reason, headers, length}. null = need more bytes (HTTPNONE); a refused
byte throws http: malformed message head. Absent slots are undefined
(uri.c's rule), status is a Number (abc u64decdrain), headers is
[[name, value], …], length is the head's byte count — the body starts
there, JS slices it off its own buffer.http._feed(head) → Uint8Array, the head object above spelled back
(CRLF CRLF included). method set → request line, else status set →
status line. A drained head re-spells byte-identically.http.c — 194 lines, new. jhttp_drain over HTTPutf8Drain,
jhttp_feed over HTTPutf8Feed, BASS carves for the token/scratch
buffers, both leaves marshalling only.CMakeLists.txt — http.c + ${ABC_DIR}/HTTP.c + HTTP.rl.c in
QUICKJAB_SRC (abc-core strips HTTP with CURL), JABChttp test gated on
EXISTS ${JAB_TEST}/http.js like JABCigno (shared test repo).JABC.h (+2 lines), main.c (+1) — the install declaration and call.test/http.js — 149 lines, new; 41 eq checks + 2 completion guards,
7 legs: request head, response head, headerless/empty-value heads,
byte-at-a-time partial feeds (29 drains, null until the last byte),
two malformed heads + a bad _feed arg, compose + drain→feed→drain round
trips, and a net.createServer loopback where both sides re-drain a
growing buffer and read the body at length.dog/; no existing test touched; no index change required
(no dog/abc header added or renamed, README lists no modules).HTTPBody = octet* swallows the body, so
data[0] after a whole-message drain is at the buffer end, not the head
end. The head is therefore measured as last lexed token end + 4 — the
grammar mandates CRLF CRLF right behind the last token (field value, or
the request/status line tail; an empty field value still fires). Verified
against a C probe over request/response/no-header/empty-value/pipelined
inputs.HTTPLexer returns HTTPBAD for both. They are
told apart by where the machine stopped — http.data[0] at the end of
input = truncated (→ HTTPNONE → null), short of it = a refused byte.FieldValue twice (the inner text and
the whole fold), so a folded head yields an odd token list and mis-paired
headers. Head length stays correct. Folding is forbidden by RFC 7230;
worth its own dog ticket if lite ever needs it.cmake -S . -B build -GNinja && ninja -C build && ctest -j16:
*122/122 passed* (121 before + the new JABChttp). A 200k-iteration
drain+feed loop stays at 8.4 MB RSS and exits 0 (no JSValue or BASS leak).
Suggested commit message:
QJAB-004: http._drain/_feed leaves over abc/HTTP