Skip to content

Commit 6b69fef

Browse files
committed
Merge TASK-052 review cleanup (31/34 fixed, 3 deferred bench design)
2 parents 25adf48 + fd8ec96 commit 6b69fef

7 files changed

Lines changed: 265 additions & 235 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1534,7 +1534,6 @@ so the registration persists for the webserver's lifetime.
15341534
|-------|----------|---------------|--------------------|
15351535
| `connection_opened` | New TCP / TLS connection accepted by MHD | No | No |
15361536
| `accept_decision` | After the default-policy / block-list verdict; the connection has been accepted or denied | No | No |
1537-
| `connection_closed` | Connection torn down (peer close or server close) | No | No |
15381537
| `request_received` | Request line and headers parsed, body not yet consumed | Yes (`hook_action`) | No |
15391538
| `body_chunk` | Each upload-body chunk delivered by MHD | Yes (`hook_action`) | No |
15401539
| `route_resolved` | After URL → resource resolution; carries the matched route or "no match" | No | No |
@@ -1543,6 +1542,7 @@ so the registration persists for the webserver's lifetime.
15431542
| `after_handler` | Handler returned a response, before it is queued on the wire (mutation point) | Yes (`hook_action`) | Yes |
15441543
| `response_sent` | Response handed to `MHD_queue_response`; carries `status`, `bytes_queued`, `elapsed` | No | Yes |
15451544
| `request_completed` | Request lifecycle finished (success or failure); last hook to fire per request | No | Yes |
1545+
| `connection_closed` | Connection torn down (peer close or server close) | No | No |
15461546

15471547
### Short-circuit semantics
15481548

RELEASE_NOTES.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -103,10 +103,10 @@ v1.x is end-of-life on the day v2.0 ships.
103103
every removed `#define`.
104104
- **Lifecycle hook bus (`webserver::add_hook` / `http_resource::add_hook`).**
105105
Eleven phases (`hook_phase` enum: `connection_opened`,
106-
`accept_decision`, `connection_closed`, `request_received`,
107-
`body_chunk`, `route_resolved`, `before_handler`,
108-
`handler_exception`, `after_handler`, `response_sent`,
109-
`request_completed`) spanning connection, request, routing, handler,
106+
`accept_decision`, `request_received`, `body_chunk`,
107+
`route_resolved`, `before_handler`, `handler_exception`,
108+
`after_handler`, `response_sent`, `request_completed`,
109+
`connection_closed`) spanning connection, request, routing, handler,
110110
and response. Multi-subscriber, server-wide and per-route. The v1
111111
single-slot setters (`log_access`, `not_found_handler`,
112112
`method_not_allowed_handler`, `internal_error_handler`,

examples/per_route_auth.cpp

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,16 @@
1818
// export AUTH_USER=alice AUTH_PASS=hunter2
1919
// ./per_route_auth
2020
//
21+
// TRANSPORT NOTE: HTTP Basic auth sends credentials base64-encoded but
22+
// NOT encrypted. In production, serve only over TLS (use
23+
// create_webserver().use_ssl(...)).
24+
//
25+
// CONSTANT-TIME NOTE: The credential comparison below uses
26+
// std::string_view::operator==, which short-circuits on the first
27+
// differing byte and can leak information via timing side-channels
28+
// (CWE-208). In production, replace with a constant-time comparison
29+
// (e.g., CRYPTO_memcmp or an equivalent fixed-length loop).
30+
//
2131
// Then:
2232
//
2333
// curl -v http://localhost:8080/public # 200 OK
@@ -81,8 +91,14 @@ int main() {
8191
auto h = priv->add_hook(hs::hook_phase::before_handler,
8292
std::function<hs::hook_action(hs::before_handler_ctx&)>(
8393
[user, pass](hs::before_handler_ctx& ctx) {
94+
// Null should never occur at before_handler on a matched
95+
// route, but fail closed (deny) rather than pass on any
96+
// unexpected null to avoid a fail-open security hole
97+
// (CWE-636).
8498
if (ctx.request == nullptr) {
85-
return hs::hook_action::pass();
99+
return hs::hook_action::respond_with(
100+
hs::http_response::unauthorized(
101+
"Basic", "private-realm", "Unauthorized"));
86102
}
87103
std::string_view u = ctx.request->get_user();
88104
std::string_view p = ctx.request->get_pass();

0 commit comments

Comments
 (0)