Skip to content

Add Fulmine.js server - #154

Merged
MDA2AV merged 1 commit into
MDA2AV:mainfrom
nigrosimone:add-fulmine-js
Aug 18, 2026
Merged

Add Fulmine.js server#154
MDA2AV merged 1 commit into
MDA2AV:mainfrom
nigrosimone:add-fulmine-js

Conversation

@nigrosimone

@nigrosimonenigrosimone commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Adds Fulmine.js as a server under test. It is a
drop-in Express 5 replacement that runs on uWebSockets.js, so its HTTP parsing is µWS's rather than
node's, and the probe says something quite different about it than about Express: 128/159 here
against Express's 147/157 on the same machine, and almost every difference is in the request line
and the chunked framing.

There is no server.js in this directory on purpose. The package is installed under the name
express, so the Dockerfile copies ExpressServer/server.js and runs it unchanged: what is probed
is the same application as the Express row with only the framework behind it swapped, which is the
claim this project exists to make. It also means the two rows cannot drift apart when that file
changes.

Two things about the Dockerfile are forced by uWebSockets.js: it is installed from a git tag rather
than from the registry, so the image needs git and an https rewrite, and its prebuilt binary needs
glibc 2.38, so the base image is node:22-trixie-slim and not -slim.

Ran locally the way the workflow does, with the container on --network host: 128/159, 213 tests,
no errors.

One note on the Sonar gate: it fails on the security rating, and what is left is the missing lock
file. .gitignore excludes lock files repo-wide, so this uses npm install with the version pinned
exactly rather than npm ci. Say the word and I will commit a package-lock.json for this
directory with an exception in .gitignore.

@nigrosimone
nigrosimone marked this pull request as ready for review August 18, 2026 17:20
@github-actions

github-actionsBot commented Aug 18, 2026

Copy link
Copy Markdown

Http11Probe — Compliance Comparison

ServerScore
Fulmine.js128/159████████████████░░░░ 81%

✅ Baseline Passed

Compliance

TestExpectedFulmine.js
BASELINE2xx200
BARE-LF-REQUEST-LINE400 or close (pass), 2xx (warn)505
BARE-LF-HEADER400 or close (pass), 2xx (warn)400
OBS-FOLD400400
SP-BEFORE-COLON400400
MULTI-SP-REQUEST-LINE400 or 2xx; close/timeout = warn505
MISSING-HOST400400
INVALID-VERSION400/505, close, or timeout = warn505
EMPTY-HEADER-NAME400 or close200
CR-ONLY-LINE-ENDING400, close, or timeout = warn505
MISSING-TARGET400, close, or timeout = warn505
FRAGMENT-IN-TARGET400 or 2xx; 404 = warn⚠️404
HTTP09-REQUEST400/close/timeout505
INVALID-HEADER-NAME400 or close400
HEADER-NO-COLON400 or close400
DUPLICATE-HOST400400
CL-NON-NUMERIC400 or closeClosedByServer
CL-PLUS-SIGN400 or closeClosedByServer
WHITESPACE-BEFORE-HEADERS400 or close400
DUPLICATE-HOST-SAME400400
HOST-WITH-USERINFO400 or close200
HOST-WITH-PATH400 or close200
ASTERISK-WITH-GET400, close, or timeout = warn505
OPTIONS-STAR2xx or 405; close/timeout = warn505
UNKNOWN-TE-501400/501 or closeClosedByServer
LEADING-CRLF400 or 2xx; close/timeout = warn⚠️TimedOut
ABSOLUTE-FORM2xx preferred; 400/close/timeout = warn505
METHOD-CASE400/405/501 or 2xx; close/timeout = warn⚠️ClosedByServer
POST-CL-BODY2xx + echo200
POST-CL-ZERO2xx or close200
POST-NO-CL-NO-TE2xx or close200
POST-CL-UNDERSEND400/close/timeoutTimedOut
CHUNKED-BODY2xx + echo200
CHUNKED-MULTI2xx + echo200
CHUNKED-EMPTY2xx or close200
CHUNKED-NO-FINAL400/close/timeoutTimedOut
METHOD-CONNECT400/405/501 or close505
EXPECT-UNKNOWN417 or 2xx⚠️200
GET-WITH-CL-BODY400 or 2xx⚠️200
CHUNKED-EXTENSION2xx preferred; 400 warns⚠️400
METHOD-TRACE405/501 or 2xx404
HOST-EMPTY-VALUE400 or close200
REQUEST-LINE-TAB400 or 2xx; close/timeout = warn505
VERSION-MISSING-MINOR400, close, or timeout = warn505
VERSION-LEADING-ZEROS400, close, or timeout = warn505
VERSION-WHITESPACE400, close, or timeout = warn505
CONNECTION-CLOSE2xx + close200
HTTP10-DEFAULT-CLOSE2xx + close505
HTTP10-NO-HOST200 or 400505
HTTP12-VERSION200 or 505⚠️505
TRACE-WITH-BODY400/405 or 200404
CHUNKED-TRAILER-VALID2xx + echo505
CHUNKED-HEX-UPPERCASE2xx + echo200
RANGE-POST2xx (Range ignored)200
HEAD-NO-BODY2xx with no body200
UNKNOWN-METHOD501/405/400 or closeClosedByServer
DATE-HEADER2xx with Date header200
DATE-FORMATIMF-fixdate format200
NO-1XX-HTTP10non-1xx response505
OPTIONS-ALLOW2xx with Allow header, or 405200
CONTENT-TYPE2xx with Content-Type200
VERSION-CASE400, close, or timeout = warn505
LONG-URL-OKnot 414; close/timeout = warn431
SPACE-IN-TARGET400, close, or timeout = warn505
DUPLICATE-CT400 or 2xx⚠️200
TRACE-SENSITIVE405/501, or 200 without Auth404
RANGE-INVALID200 or 416200
ACCEPT-NONSENSE406 or 2xx⚠️200
POST-UNSUPPORTED-CT415 or 2xx200

Smuggling

TestExpectedFulmine.js
CL-TE-BOTH400 or 2xx400
DUPLICATE-CL400 or closeClosedByServer
CL-LEADING-ZEROS400 or 2xx⚠️200
TE-XCHUNKED400/501 or close400
TE-TRAILING-SPACE400/501 or 2xx+close400
TE-SP-BEFORE-COLON400 or close400
CL-NEGATIVE400 or closeClosedByServer
CLTE-PIPELINE400 or close preferred; 2xx acceptable400
TECL-PIPELINE400 or close preferred; 2xx acceptable400
CL-TRAILING-SPACE400 or 2xx⚠️200
TE-DOUBLE-CHUNKED400 or 2xx400
CL-EXTRA-LEADING-SP400 or 2xx⚠️200
TE-CASE-MISMATCH400 or 2xx400
CL-COMMA-DIFFERENT400 or closeClosedByServer
TE-NOT-FINAL-CHUNKED400 or closeClosedByServer
TE-HTTP10400 or close505
CHUNK-BARE-SEMICOLON400 or closeTimedOut
CHUNK-EXT-INVALID-TOKEN400 or close400
BARE-CR-HEADER-VALUE400 or closeTimedOut
CL-OCTAL400 or closeClosedByServer
CHUNK-UNDERSCORE400 or close400
TE-EMPTY-VALUE400 or closeClosedByServer
TE-LEADING-COMMA400 or 2xx400
TE-DUPLICATE-HEADERS400 or close400
CHUNK-HEX-PREFIX400 or close400
CHUNK-SIZE-PLUS400 or close400
CHUNK-SIZE-TRAILING-OWS400 or close200
CL-HEX-PREFIX400 or closeClosedByServer
CL-INTERNAL-SPACE400 or closeClosedByServer
CHUNK-LEADING-SP400 or close200
CHUNK-MISSING-TRAILING-CRLF400 or close200
CHUNK-EXT-LF400 or 2xxTimedOut
CHUNK-SPILL400 or close200
CHUNK-LF-TERM400 or 2xx⚠️200
CHUNK-EXT-CTRL400 or closeTimedOut
CHUNK-EXT-CR400 or closeTimedOut
TE-VTAB400 or close400
TE-FORMFEED400 or close400
TE-NULL400 or close400
CHUNK-LF-TRAILER400 or 2xx⚠️200
TE-IDENTITY400/501 or close400
CHUNK-NEGATIVE400 or close400
TRANSFER_ENCODING400 or 2xx⚠️200
CL-COMMA-SAME400 or 2xxClosedByServer
CL-COMMA-TRIPLE400 or 2xxClosedByServer
CHUNKED-WITH-PARAMS400 or 2xx400
EXPECT-100-CL100, 400 or 2xx⚠️100
TRAILER-CL400 or 2xx505
TRAILER-TE400 or 2xx505
TRAILER-HOST400 or 2xx505
TRAILER-AUTH400 or 2xx505
HEAD-CL-BODY400 or 2xx⚠️200
OPTIONS-CL-BODY400/405 or 2xx⚠️200
CL-UNDERSCORE400 or closeClosedByServer
CL-NEGATIVE-ZERO400 or closeClosedByServer
CL-DOUBLE-ZERO400 or 2xx⚠️200
CL-LEADING-ZEROS-OCTAL400 or 2xx⚠️200
TE-OBS-FOLD400 or 2xx+close400
TE-TRAILING-COMMA400 or 2xx400
TE-TAB-BEFORE-VALUE400 or 2xx400
ABSOLUTE-URI-HOST-MISMATCH400 or 2xx505
MULTIPLE-HOST-COMMA400 or close200
CHUNK-BARE-CR-TERM400 or closeTimedOut
TRAILER-CONTENT-TYPE400 or 2xx505
CLTE-CONN-CLOSE400, or 2xx + close400
TECL-CONN-CLOSE400, or 2xx + close400
CLTE-DESYNC400, or close400
CLTE-SMUGGLED-GET400, or close (no extra response)400
CLTE-SMUGGLED-GET-CL-PLUS400, or close (no extra response)400
CLTE-SMUGGLED-GET-CL-NON-NUMERIC400, or close (no extra response)400
CLTE-SMUGGLED-GET-TE-OBS-FOLD400, or close (no extra response)400
CLTE-SMUGGLED-HEAD400, or close (no extra response)400
CLTE-SMUGGLED-GET-TE-TRAILING-SPACE400, or close (no extra response)400
CLTE-SMUGGLED-GET-TE-LEADING-COMMA400, or close (no extra response)400
CLTE-SMUGGLED-GET-TE-CASE-MISMATCH400, or close (no extra response)400
TE-DUPLICATE-HEADERS-SMUGGLED-GET400, or close (no extra response)400
TECL-SMUGGLED-GET400, or close (no extra response)400
DUPLICATE-CL-SMUGGLED-GET400, or close (no extra response)ClosedByServer
GET-CL-PREFIX-DESYNC400/close preferred; extra response on step 2 = warn⚠️200
TECL-DESYNC400, or close400
CL0-BODY-POISON400/close preferred; poisoned follow-up = warn⚠️200
GET-CL-BODY-DESYNC400/close/pass-through; poisoned follow-up = warn200
OPTIONS-CL-BODY-DESYNC400/close/pass-through; poisoned follow-up = warn200
EXPECT-100-CL-DESYNC417/400/close preferred; poisoned follow-up = warn⚠️200
OPTIONS-TE-OBS-FOLD400, or 2xx + close400
CHUNK-INVALID-SIZE-DESYNC400, or close400
PIPELINE-SAFE2xx + 2xx200

Malformed Input

TestExpectedFulmine.js
BINARY-GARBAGE400/close/timeout505
LONG-URL400/414/431 or close431
LONG-HEADER-VALUE400/431 or close431
MANY-HEADERS400/431 or close431
NUL-IN-URL400 or close505
CONTROL-CHARS-HEADER400 or close400
INCOMPLETE-REQUEST400/close/timeoutTimedOut
EMPTY-REQUEST400/close/timeoutTimedOut
LONG-HEADER-NAME400/431 or close431
LONG-METHOD400 or close431
NON-ASCII-HEADER-NAME400 or close400
NON-ASCII-URL400 or closeClosedByServer
CL-OVERFLOW400 or closeClosedByServer
WHITESPACE-ONLY-LINE400/close/timeout505
NUL-IN-HEADER-VALUE400 or close400
CHUNK-SIZE-OVERFLOW400 or close400
H2-PREFACE400/505/close/timeout505
CL-EMPTY400 or closeClosedByServer
CL-TAB-BEFORE-VALUE400 or 2xx⚠️200
URL-BACKSLASH400 or 2xx/404⚠️404
URL-OVERLONG-UTF8400 or closeClosedByServer
URL-PERCENT-NULL400 or 2xx/404⚠️404
URL-PERCENT-CRLF400 or 2xx/404⚠️404
CHUNK-EXT-64K400 or 2xx400
RANGE-OVERLAPPING200/206/400/416⚠️200
POST-CL-HUGE-NO-BODY400/413/close/timeoutTimedOut

Header Normalization

TestExpectedFulmine.js
UNDERSCORE-CLReject/drop (pass), normalize (fail), preserve (warn)⚠️200
SP-BEFORE-COLON-CLReject/drop (pass), normalize (fail), preserve (warn)400
TAB-IN-NAMEReject/drop (pass), normalize (fail), preserve (warn)400
CASE-TEReject/drop (pass), normalize casing (fail), preserve (warn)400
UNDERSCORE-TEReject/drop (pass), normalize (fail), preserve (warn)⚠️200

Commit: 20bb54c

@sonarqubecloud

Copy link
Copy Markdown

Quality Gate FailedQuality Gate failed

Failed conditions
C Security Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

@MDA2AV
MDA2AV merged commit 555583f into MDA2AV:mainAug 18, 2026
1 of 2 checks passed
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@nigrosimone@MDA2AV