Skip to content

Pin the HTTP command server's behaviour before hardening it - #174

Merged
HugoFara merged 1 commit into
devfrom
test/http-server-characterisation
Aug 12, 2026
Merged

Pin the HTTP command server's behaviour before hardening it#174
HugoFara merged 1 commit into
devfrom
test/http-server-characterisation

Conversation

@HugoFara

Copy link
Copy Markdown
Collaborator

Nothing tested the HTTP server, and it is due for changes to request parsing and path resolution. These seven cases record what it does today, so a regression shows up here rather than as a blank map in someone's browser.

Purely additive: no change to how the server behaves.

What the web console depends on

Both are covered, and any hardening has to preserve them:

The ff: endpoint is the entire UI-to-engine channel.forefireGUI.jssendCommand() posts to / with a body of ff:<command>. It cannot be removed or authenticated away without redesigning the console.

Files resolve against the working directory.buildPlotCommand emits plot[parameter=fuel;filename=fuel.png;...], ForeFire writes fuel.png beside the case, and the browser then fetches /fuel.png as a static file. A document root confined to tools/htdocs would break every map overlay — this is the trap most likely to be hit by a well-intentioned path fix.

Cases

CasePins
the server binds and accepts a connectionbasic liveness
a file in the working directory is servedthe plot-overlay path
a missing file returns 404
a POST body prefixed with ff: reaches the command callbackthe console channel, and that the prefix is stripped
a GET uri prefixed with /ff: reaches the command callbackthe alternate form
an ordinary file request does not reach the command callbackthe static/command split
a request comfortably inside one buffer round-trips intacta size the console can rely on today

Deliberately not covered: path traversal

A test asserting the current behaviour would document an unfixed weakness in a public repository. That case belongs with the fix, when the assertion can be that the request is refused.

Two problems found while writing this, neither fixed here

HttpCommandServer.hpp was not self-contained. It used std::ifstream without including <fstream>, and an unqualified cout, so it compiled only when included after a header that happened to supply both — Command.h was the only such place. Fixed by adding the include and qualifying cout, because the test cannot include the header otherwise. Compile-only; no behaviour change.

stop() deadlocks. It sets running = false, closes the listening socket, then joins the accept thread — but closing a socket does not reliably wake a thread blocked in accept() on Linux, so the join never returns. My first version of this suite hung for exactly this reason.

The suite therefore starts one server and deliberately never stops it; the reasoning is in a comment so nobody "tidies" it later. Nothing has noticed until now because the server is never stopped in normal use — it runs until the process exits. Fixing it needs shutdown() or a self-pipe, which is a change to server behaviour and so is deferred with the rest of the hardening.

Verification

  • Full suite: 29 cases, 2151 assertions, all passing; ctest 4/4.
  • Stable under --order-by=rand across three seeds.
  • runff unchanged — KML and NetCDF both within tolerance.
  • Scratch files are cleaned up; no stray artifacts left in the tree.

Drafted by Claude Opus 5. Reviewed by a maintainer before filing.

Nothing tested the HTTP server, and it is due for changes to request
parsing and path resolution. These seven cases record what it does today,
so a regression shows up here rather than as a blank map in a browser.
Two behaviours the web console depends on and that any hardening must
preserve:
- POST / with a body of "ff:<command>" reaches the interpreter. That is
the entire UI-to-engine channel (forefireGUI.js sendCommand).
- Files resolve against the working directory. The console issues
plot[filename=fuel.png], ForeFire writes fuel.png beside the case,
and the browser fetches /fuel.png as a static file. A document root
that does not cover both htdocs and the working directory would break
every overlay.
Deliberately not covered: path traversal. Asserting the current
behaviour would document an unfixed weakness in a public repository. Its
test belongs with the fix, when the assertion can be that the request is
refused.
Two problems found while writing this, neither fixed here:
- HttpCommandServer.hpp was not self-contained. It used std::ifstream
without including <fstream> and an unqualified cout, so it compiled
only when included after a header that supplied both. Fixed, because
the test cannot include it otherwise; no behaviour change.
- stop() deadlocks. It closes the listening socket and then joins the
accept thread, but closing a socket does not reliably wake a thread
blocked in accept() on Linux, so the join never returns. The suite
therefore starts one server and never stops it. Fixing that needs
shutdown() or a self-pipe and belongs with the hardening work.
@HugoFaraHugoFara self-assigned this Aug 12, 2026
@HugoFara
HugoFara merged commit e1df887 into devAug 12, 2026
3 checks passed
@antonio-leblanc
antonio-leblanc deleted the test/http-server-characterisation branch August 13, 2026 02:30
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@HugoFara