feat: COR_HTTP_SERVER=builtin — a broker with no HTTP library - #67
Merged
Conversation
ldd coraine | grep microhttpd # mhd: one line
# builtin: nothing
`builtin` was refused at configure time because the backend it selected did not
exist. It exists now (corRest, corHttp), so the refusal goes and libcorHttp.a
joins the link — after libcorRest.a, since that is what calls into it.
full build (mhd) 641 tests, 641 passed
built-in 640 tests, 640 passed
ETSI, built-in 1046 TPs, 1046 passed
`coraine --version` gains a `httpServer:` line. NOT folded into `features:`
above it: those are booleans answering "is this capability in the build", and
this is a choice between two implementations of a capability that is always in
it — a feature name whose "off" meant nothing. It is also READ differently, and
that is the part that matters here: the harness registers `-httpServer` with the
tag HTTPSERVER, so a test file says `REQUIRE_HTTPSERVER: mhd` and means "one
current value out of alternatives", where `REQUIRE_FEATURE: A B` means "A and
B". Detected from the binary like COR_TEST_FEATURES, and NONE when the binary
cannot be asked, so a failed detection makes the marker inert instead of
filtering out every test that carries one. GET /build already reports the same
thing to a running broker; this line is what answers before one has started.
Exactly one test needs the marker: the built-in server has no TLS, so the HTTPS
notification receiver cannot be raised against it. The broker's own side —
notifying an https endpoint — is the client stack and is the same in both.
⭐ AND THREE STEPS OF query_entities_scope THAT HAD NEVER TESTED WHAT THEY SAID.
Steps 08, 16 and 20 send the NGSI-LD single-level scope wildcard,
`scopeQ=/Madrid/+/ParqueNorte`, and each expected `[]`. A query string is
form-encoded in practice — urlencode/quote_plus is what every HTTP client
library produces — so a raw `+` on the wire is a SPACE to any server that reads
it: the broker was asked for a middle level consisting of one space, matched
nothing, and answered 200 with an empty array. Three green steps asserting that
the wildcard does not work. Percent-encoded, `%2B`, both servers hand the broker
the `+` the spec means, and the steps now assert the matches their own comments
have always claimed.
Step 16 turns out to match E4 as well: `/Madrid/%2B/#` covers `/Madrid/Districts`
because `#` matches its own level and not only levels below it.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TGatXwrHx1CreL49sCuS37
A pull request builds ONE of them — `mhd`, the default — so nothing on a PR
would notice `builtin` rotting. Doubling the two-minute PR check to answer a
question that changes once a month is the wrong trade; the nightly is where the
slow half already lives.
So `COR_HTTP_SERVER` becomes a matrix axis on the two jobs that answer it:
valgrind 4 shards x 2 servers. A valgrind run is a FUNCTIONAL run as well -
it fails on an output mismatch exactly as the plain suite does - so
one matrix answers both "does it still pass" and "does it still
leak". Which is the pairing that matters here: the built-in server
arrived with a use-after-the-connection-moved-on and a deadlock.
etsi 2 servers. A conformance claim is about the DEPLOYMENT, and the
HTTP server is part of the deployment. The six TPs the built-in one
first failed were all query strings the functional suite never
sends — `q=name=="Eiffel Tower"`, form-encoded, with the space on
the wire as a `+` — so the functional suite could not have caught
them, and did not.
COR_HTTP_SERVER goes on `make di`, which passes it down to corRest's own make as
well as to cmake. Setting it on one side only links a broker against a corRest
compiled the other way, and nothing reports that. `coraine --version` is echoed
after the build so the job's log says which server it actually got.
Artifact names carry the leg (`etsi-results-builtin`, `valgrind-builtin-1-156`):
two jobs uploading one artifact name is a conflict whose winner is whichever
finished last.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TGatXwrHx1CreL49sCuS37
Base automatically changed from
feat/conditional-compilation-subscriptions
to
main
September 5, 2026 20:46
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #66, which is where the switch was plumbed. Base retargets to
mainautomatically when #66 merges. Needs corRest#8 (and, for the nightly'sbuiltinlegs only, corLibs#7).mhdbuiltinPlus 147/147
E:0 L:0 F:0valgrind over the notification/subscription/distopcases under
builtin.--versiongains ahttpServer:lineNot folded into
features:above it. Those are booleans answering is thiscapability in the build; this is a choice between two implementations of a
capability that is always in it — a feature name whose "off" would mean nothing.
It is also read differently, which is the part that matters: the harness
registers
-httpServerwith the tagHTTPSERVER, so a test saysREQUIRE_HTTPSERVER: mhdand means one current value out of alternatives,where
REQUIRE_FEATURE: A Bmeans A and B. Detected from the binary, andNONEwhen it cannot be asked, so a failed detection makes the marker inertinstead of filtering out every test carrying one.
Exactly one test needs it: the built-in server has no TLS, so the HTTPS
notification receiver cannot be raised against it. The broker's own side —
notifying an
httpsendpoint — is the client stack and is the same in both.Three steps of
query_entities_scopethat had never tested what they saidSteps 08, 16 and 20 send the NGSI-LD single-level scope wildcard,
scopeQ=/Madrid/+/ParqueNorte, and each expected[]. A query string isform-encoded in practice, so a raw
+on the wire is a space to any serverthat reads it: the broker was asked for a middle level consisting of one space,
matched nothing, and answered 200 with an empty array. Three green steps
asserting that the wildcard does not work. Percent-encoded (
%2B) both servershand the broker the
+the spec means, and the steps now assert the matchestheir own comments always claimed.
Step 16 then also matches E4:
/Madrid/%2B/#covers/Madrid/Districts,because
#matches its own level and not only the levels below it.The nightly runs both servers
A PR builds one —
mhd, the default — so nothing on a PR would noticebuiltinrotting, and doubling a two-minute check to answer a question that changes once
a month is the wrong trade.
COR_HTTP_SERVERis now a matrix axis on the twonightly jobs that answer it: valgrind (4 shards × 2 servers — a valgrind run
is a functional run too, so one matrix covers passes and leaks) and etsi
(2 servers — the six TPs the built-in server first failed were query strings the
functional suite never sends).
🤖 Generated with Claude Code
https://claude.ai/code/session_01TGatXwrHx1CreL49sCuS37