3.9 KiB
Where the code in this directory comes from
Two separate works live here, under two separate MIT notices, and the difference matters when either is updated.
lib/ — llhttp, upstream and unmodified
- Version: 9.4.3
- Source: https://github.com/nodejs/llhttp, tag
release/v9.4.3(30 July 2026) - Tarball:
https://github.com/nodejs/llhttp/archive/refs/tags/release/v9.4.3.tar.gz(sha256:1eb813c7437b31a87496a1cd3ed79f00746720f5e7e29c79b42c02cb69f36c39) - Licence: MIT, © Fedor Indutny and contributors —
lib/LICENSE.llhttp
Four files, copied verbatim from that tag, and nothing in them has been edited:
| here | upstream | sha256 |
|---|---|---|
lib/llhttp.h |
include/llhttp.h |
5bc82fa51b19aa8bee7d921038393fbfc74e8cc9bae0844c2d82c102fb8cfd68 |
lib/llhttp.c |
src/llhttp.c |
391e7c99912abf3b1c9dd8a9c85fdeaac2663e9fa55b6f3871154d16fef8b892 |
lib/api.c |
src/api.c |
0f8590206fe2f264db2825401b5fb856b979ee1363dc88b06f36dc9577afb941 |
lib/http.c |
src/http.c |
a1f2b23168f8e9b5bfa464c89027d3ca259fc649ae3d7e72bfff997d1aeb5d72 |
llhttp.c is generated upstream, from the TypeScript that describes the state
machine; the release/* tags are the branch where that output is committed, which is
why these can be taken as source without a Node toolchain. There is no api.h: the
public header is one file and already carries what that used to declare. It was here
until 9.4.3, included by nothing.
Updating
Replace those four files from the new tag, update the table above, rebuild, and run
pytest unit/test_http_parsing.py from tests/. The binding needs no change for a
minor release: parser_settings is built with designated initialisers, so a callback
added upstream (on_protocol_complete arrived in 9.3.0) stays NULL, and the error list
is generated from HTTP_ERRNO_MAP, so new codes bring their own exceptions along.
What does need looking at is the other direction: each release changes what the parser
accepts. Going from 9.2.1 to 9.4.3, an empty Transfer-Encoding stopped being
accepted and tabs around Content-Length started being. Both are pinned in
tests/unit/test_http_parsing.py — a change there is a decision about what filters see,
not a test to fix.
llhttp_module.c — the Python binding, ours
Derived from pyllhttp (itself a fork of Derrick
Lyndon Pallas' pyllhttp, now archived), and modified. Licence: MIT —
LICENSE.pyllhttp.
What differs from that fork, which is what to re-apply if anything is ever taken from it again:
- It is built as
firegex._llhttpand declaresPy_MOD_PER_INTERPRETER_GIL_SUPPORTED, which is what lets it load in the subinterpreterscpproxyruns filters in — the reason none of the alternatives with prebuilt wheels can be used. - Nothing here reaches for
pyllhttpany more. The types and the exception classes carry this module's name, and the error path looks the class up in this module throughsys.modules, so each interpreter finds the classes it built. It used toPyImport_ImportModule("pyllhttp")on every parse error: that package is not a dependency and is installed on no machine the wheel is, so the import failed, printed its traceback to stderr — the service log, on a filter — and returned without setting an exception, which CPython reports asSystemError: ... returned NULL without setting an exception. A malformed request said that instead of naming the parse error. Pinned bytests/unit/test_llhttp_binding.py, which takespyllhttpaway before asking, and bywheel_smoke.py, whichcibuildwheelruns where it was never there. - The exception class names are derived into a local buffer instead of being
malloced once onto a process-global table and never freed — that table is shared by every interpreter, which is not somewhere a module claiming per-interpreter support may write.