You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Apply selected post-review minor fixes:
- CWE-117: sanitize control chars in log_access alias path/method (and
in examples/clf_access_log.cpp) to prevent log-line injection.
- Perf: skip steady_clock::now() in fire_response_sent_gated when only
the log_access alias slot fires (alias does not read elapsed).
- Doxygen block on create_webserver::log_access() pointing users to
add_hook(response_sent, ...) for structured ctx.
- Architecture doc: update hooks.md firing-site references to the new
webserver_request.cpp / webserver_callbacks.cpp split.
- Test wiring: add -lmicrohttpd to hooks_log_access_alias_slot LDADD.
Persist full reviewer findings under specs/unworked_review_issues/.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|`handler_exception`|`webserver.cpp:dispatch_resource_handler` — each catch arm |**yes** (maps exception to response) | yes |
16
16
|`after_handler`| between handler return and `materialize_and_queue_response`|**yes** (replaces response) | yes |
17
-
|`response_sent`|`webserver.cpp:materialize_and_queue_response` — post `MHD_queue_response`| no | yes |
18
-
|`request_completed`|`webserver.cpp:request_completed` — NOTIFY_COMPLETED | no | yes |
17
+
|`response_sent`|`webserver_request.cpp:materialize_and_queue_response` — post `MHD_queue_response`| no | yes |
18
+
|`request_completed`|`webserver_callbacks.cpp:request_completed` — NOTIFY_COMPLETED | no | yes |
19
19
|`connection_closed`|`webserver.cpp:connection_notify` — NOTIFY_CLOSED | no | no |
20
20
21
21
**Implementation.** Each phase has its own `std::vector<std::function<...>>` in `webserver_impl`, guarded by a single `std::shared_mutex hook_table_mutex_`. A per-phase `std::atomic<bool> any_hooks_[hook_phase::count_]` flag short-circuits the dispatch site to a relaxed atomic load and a compare-with-zero when no subscribers exist — the only hook-related cost on the hot request path for a server with zero hooks registered.
Copy file name to clipboardExpand all lines: specs/tasks/M5-routing-lifecycle/TASK-050.md
+6-6Lines changed: 6 additions & 6 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -8,11 +8,11 @@
8
8
Wire the three tail-end phases. `after_handler` is the post-handler short-circuit (it can REPLACE the in-flight response). `response_sent` is the observation point that finally has the response, status, byte-count, and timing — the data #281 and #69 have been asking for. `request_completed` is the unconditional final hook. Convert `log_access` into the documented alias.
9
9
10
10
**Action Items:**
11
-
-[] Fire `after_handler` between `dispatch_resource_handler` and `materialize_and_queue_response` in `webserver_impl::finalize_answer` (`webserver.cpp:2444` → `webserver.cpp:2449`). Context: `after_handler_ctx { const http_request& req; http_response& resp; }` — mutable response reference so a hook can `resp.with_header(...)` in place. Short-circuit semantics: a hook returning `hook_action::respond_with(r2)` REPLACES `mr->response_` with `r2` and skips remaining hooks at the phase. Subsequent hooks at later phases (`response_sent`, `request_completed`) still fire on the replaced response.
12
-
-[] Fire `response_sent` immediately after the `MHD_queue_response` call in `webserver_impl::materialize_and_queue_response` (`webserver.cpp:2421`), BEFORE `MHD_destroy_response`. Context: `response_sent_ctx { const http_request& req; const http_response& resp; int status; std::size_t bytes_queued; std::chrono::nanoseconds elapsed; }`. `elapsed` is measured from `answer_to_connection`'s first invocation for this `mr` (timestamp captured in `modded_request` at TASK-045 time).
13
-
-[] Fire `request_completed` from `webserver_impl::request_completed` (`webserver.cpp:1253`), BEFORE the `delete static_cast<detail::modded_request*>(*con_cls)` step (otherwise the context fields would dangle). Context: `request_completed_ctx { const http_request& req; const http_response* resp; bool succeeded; }`. `resp` is nullable — on early failures (`accept_decision` rejection, etc.) there may be no response object.
14
-
-[]**Alias: `log_access(fn)`.** Internally register a `response_sent` hook that formats the request line as today and invokes `fn(line)`. Re-registration replaces. Doxygen notes it as an alias and recommends`add_hook(hook_phase::response_sent, ...)` for users who want the structured context (status, bytes, timing — what #281 and #69 actually asked for).
15
-
-[]`examples/clf_access_log.cpp`: a Common-Log-Format access logger as a `response_sent` hook, demonstrating that the long-requested CLF / `time-taken` format is now writable in user code without a library change. Closes issues #281 and #69 from the user-facing-doc perspective.
11
+
-[x] Fire `after_handler` between `dispatch_resource_handler` and `materialize_and_queue_response` in `webserver_impl::finalize_answer` (implemented in `src/detail/webserver_finalize.cpp:fire_after_handler_gated`, called from `src/detail/webserver_request.cpp:finalize_answer`). Context: `after_handler_ctx { const http_request& req; http_response& resp; }` — mutable response reference so a hook can `resp.with_header(...)` in place. Short-circuit semantics: a hook returning `hook_action::respond_with(r2)` REPLACES `mr->response_` with `r2` and skips remaining hooks at the phase. Subsequent hooks at later phases (`response_sent`, `request_completed`) still fire on the replaced response.
12
+
-[x] Fire `response_sent` immediately after the `MHD_queue_response` call in `webserver_impl::materialize_and_queue_response` (`src/detail/webserver_request.cpp:materialize_and_queue_response`), BEFORE `MHD_destroy_response`. Context: `response_sent_ctx { const http_request& req; const http_response& resp; int status; std::size_t bytes_queued; std::chrono::nanoseconds elapsed; }`. `elapsed` is measured from `answer_to_connection`'s first invocation for this `mr` (timestamp captured in `modded_request` at TASK-045 time).
13
+
-[x] Fire `request_completed` from `webserver_impl::request_completed` (`src/detail/webserver_callbacks.cpp`), BEFORE the `delete static_cast<detail::modded_request*>(*con_cls)` step (otherwise the context fields would dangle). Context: `request_completed_ctx { const http_request& req; const http_response* resp; bool succeeded; }`. `resp` is nullable — on early failures (`accept_decision` rejection, etc.) there may be no response object.
14
+
-[x]**Alias: `log_access(fn)`.** Internally registers a `response_sent` hook via dedicated alias slot (`webserver_impl::log_access_alias_`) that formats the request line and invokes `fn(line)`. Re-registration replaces. Control characters are sanitized (CWE-117). Doxygen block added to `create_webserver::log_access()` noting it as an alias and recommending`add_hook(hook_phase::response_sent, ...)` for structured context (status, bytes, timing — what #281 and #69 actually asked for).
15
+
-[x]`examples/clf_access_log.cpp`: a Common-Log-Format access logger as a `response_sent` hook, demonstrating that the long-requested CLF / `time-taken` format is now writable in user code without a library change. Closes issues #281 and #69 from the user-facing-doc perspective.
16
16
17
17
**Dependencies:**
18
18
- Blocked by: TASK-045
@@ -32,4 +32,4 @@ Wire the three tail-end phases. `after_handler` is the post-handler short-circui
0 commit comments