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
Lands the 6-point dispatch error-propagation contract from §5.2 /
PRD-FLG-REQ-002 / DR-009.
API change (v2.0 breaking, intentional):
- `internal_error_handler_t = std::function<http_response(const
http_request&, std::string_view)>` is a new typedef carrying the
originating exception's message. `error_handler` continues to serve
`not_found_handler` and `method_not_allowed_handler` (which receive
no message). The widening is the smallest deviation consistent with
action item 2 ("invoke `internal_error_handler` with `e.what()`").
Dispatch path (`webserver_impl::finalize_answer`):
- Replaces the single `catch (...)` with the contract's two-branch
form: `catch (const std::exception& e)` forwards `e.what()` to the
user handler; `catch (...)` forwards the literal `"unknown
exception"`. Each arm logs via `parent->log_error` first.
- New `run_internal_error_handler_safely(mr, msg)` contains a possible
double-throw from the user handler. On re-throw it logs generically
and returns a hardcoded empty-body 500 via
`internal_error_page(mr, "", force_our=true)`.
- `internal_error_page` now takes `(mr, msg, force_our=false)`:
* `force_our=true` -> `http_response::empty().with_status(500)`.
* handler set -> invoke it with `(*mr->dhr, msg)`.
* handler unset -> default body == `msg` so the unset-handler
path is informative for debugging.
- The three non-handler-throw call sites that synthesise a 500
(handler-returned-null, materialize-returned-null, materialize-
threw) now route through `run_internal_error_handler_safely` so a
misbehaving user handler can't escape into libmicrohttpd.
`feature_unavailable` (a `std::runtime_error` subclass) lands as a
generic 500 — no special status mapping per DR-009 point 5.
Tests:
- 8 new `dr009_*` integration tests in `test/integ/basic.cpp` pin all
four acceptance criteria (message-surfaces-in-body,
message-passed-to-handler, logged-via-error_logger, empty-body-on-
double-throw, generic-log-on-double-throw, unknown-exception-
sentinel, feature_unavailable-as-500). Capturing handlers/loggers
use std::mutex since MHD invokes them concurrently.
- `exception_forces_500`, `untyped_error_forces_500`,
`file_serving_resource_missing`, `file_serving_resource_dir`
updated: body assertions changed from `== "Internal Error"` to
substring-find of the new diagnostic message.
- `internal_error_handler_also_throws`, `builder_internal_error_
handler`, `create_webserver_explicit_test` updated to the widened
handler signature. The explicit test gains a static_assert pinning
that the legacy single-arg signature is now rejected.
Documentation:
- Class-level Doxygen on `webserver` lists the 6 points verbatim with
cross-references to PRD-FLG-REQ-002 and DR-009.
- Per-setter Doxygen on `create_webserver::internal_error_handler`
documents the new signature, the unset-handler default, the
double-throw contract, and `feature_unavailable`'s 500 status.
- Inline comments on `internal_error_page`, `log_dispatch_error`, and
`run_internal_error_handler_safely` document the contract from the
implementation side. README pass is M6 (TASK-041).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
0 commit comments