feat(http1): dispatch unmatched paths to an optional fallback handler
The route map only answers paths that are known when the listener is built. A route with an unbounded segment — /shop/<slug>, /order/<token>, /posts/<id> — cannot be pre-registered: the token space is unbounded and the product set changes while the server runs. Every such request became a synthetic 404 that the application never got to see. Add one optional member, called for anything `routes` missed, with the full target still in request.path. Precedence is exact path, then the query-stripped path, then fallback, then the 404 as before, so a default-constructed listener behaves byte-identically and no call site changes. A hook rather than a pattern syntax: consumers that already have a router — one shared between a wasm frontend and the server, so a URL cannot mean different things to a crawler and to the app — keep using it, and there is no second route table to disagree with the first. PathWithoutQuery moves out of this file into :HTTP as an exported PathWithoutQueryHTTP, since ListenerHTTP now needs the same split and a fallback handler almost always does too. ListenerAsyncHTTP1 starts accepting inside its constructor, so assigning `listener.fallback` afterwards would race the accept loop; it gets a constructor overload that installs the fallback before the thread starts.
This commit is contained in:
parent
219a31a8f7
commit
4d5ef7c96b
3 changed files with 54 additions and 14 deletions
|
|
@ -29,6 +29,15 @@ namespace Crafter {
|
|||
std::string body;
|
||||
};
|
||||
|
||||
// Everything in a request target up to '?'. Both listeners dispatch on
|
||||
// this when the full target is not a registered route, so `/thing?x=1`
|
||||
// reaches the handler registered for `/thing`: browsers append query
|
||||
// strings freely and registering every variant is not a workable API.
|
||||
// Exported because a fallback handler generally needs the same split.
|
||||
export inline std::string_view PathWithoutQueryHTTP(std::string_view target) {
|
||||
return target.substr(0, target.find('?'));
|
||||
}
|
||||
|
||||
export inline HTTPRequest CreateRequestHTTP(std::string method, std::string path, std::string authority) {
|
||||
HTTPRequest r;
|
||||
r.method = std::move(method);
|
||||
|
|
|
|||
Loading…
Reference in a new issue