Routing behavior
HTTP path matching, 404 and 405, HEAD fallback, OPTIONS, CORS preflight, wildcards, and URL decoding after host.build().
This page is the runtime behavior reference for HTTP routing and method dispatch after host.build(). Registration APIs live in Routing overview and Inline route handlers.
Overview
Section titled “Overview”Each registered path becomes one pipeline: a single match target shared by every HTTP method you registered on that path. On each request, Flare:
- Matches the request pathname (no query string).
- Resolves the HTTP method (including HEAD fallback and OPTIONS shortcuts).
- Extracts route parameters when a handler will run.
- Runs middleware and the handler.
Malformed pathnames return 400 and an unbuilt host returns 503 before step 1. Steps 1-2 can return 404, 405, or 204 (OPTIONS/CORS) without running middleware. host.http.error() only handles errors thrown inside a matched pipeline.
Path composition
Section titled “Path composition”| Registration | Effective path |
|---|---|
Arc: host.http.get("/health", …) | /health |
Group: g.get("/health", …) with prefix /v1 | /v1/health |
Arc: host.http.controller("/users", Cls) | /users + decorator path |
Group: g.controller("/users", Cls) with prefix /v1 | /v1/users + decorator path |
For controllers, use "" (not "/") for a controller root route.
Segment syntax
Section titled “Segment syntax”| Segment form | Meaning | Specificity score |
|---|---|---|
Literal (users, v1) | Exact segment text | +2 per segment |
Parameter (:id, :name) | One path segment | +1 per segment |
Wildcard (*path, *rest) | Final segment only; captures one or more trailing segments (/assets alone does not match /assets/*path) | +0 |
Build-time validation rejects missing param names, wildcards not in the last position, duplicate parameter names, and duplicate methods on the same path (inline registration of a duplicate method throws immediately, before build()). Up to 1024 distinct paths per host.
Specificity and tie-breaking
Section titled “Specificity and tie-breaking”Higher specificity score wins when multiple patterns could match. When scores tie, registration order breaks the tie (earlier registration wins).
Example: for /files/readme.txt, /files/readme.txt beats /files/:name beats /files/*path when all three are registered.
Inbound path rules
Section titled “Inbound path rules”Flare rejects the request with 400 when the inbound pathname fails:
| Rule | Example invalid | Example valid |
|---|---|---|
Must start with / | users, "" | /users |
No trailing / except root | /users/ | /users, / |
No empty segments (//) | /a//b | /a/b |
| At most 8192 characters | a 9000-character pathname | any ordinary URL path |
/users/ does not fall through to /users. No middleware or handler runs for invalid pathnames.
URL decoding
Section titled “URL decoding”Captured values pass through decodeURIComponent before exposure on ctx.req.rawRouteParams and typed route fields from contracts. Malformed % sequences return 400 with a JSON error body. No middleware or handler runs.
Decoding happens after matching, so an encoded slash stays one segment for matching and becomes a literal / in the decoded value: GET /files/a%2Fb matches /files/:name with name === "a/b". The same applies to encoded . and ... Validate decoded params before using them in filesystem paths or storage keys; a route param is one path segment on the wire, not a value guaranteed to be slash-free.
Supported methods
Section titled “Supported methods”Flare dispatches GET, POST, PUT, PATCH, DELETE, HEAD, and OPTIONS. Any other method on a matched path returns 405.
Path not found (404)
Section titled “Path not found (404)”| Field | Value |
|---|---|
| Status | 404 |
| Body | Plain text Not Found |
This is not routed through host.http.error(). For a custom 404, see Custom 404 responses.
Method not allowed (405)
Section titled “Method not allowed (405)”| Field | Value |
|---|---|
| Status | 405 |
| Body | Plain text Method Not Allowed |
Allow | Methods with handlers on that path, plus HEAD when GET exists |
Allow never includes OPTIONS automatically (CORS included); it lists OPTIONS only when an explicit OPTIONS handler is registered on the path.
HEAD fallback
Section titled “HEAD fallback”When the request method is HEAD:
- If an explicit HEAD handler is registered, it runs.
- Otherwise, if a GET handler exists, Flare runs GET and returns the same status and headers with a null body.
OPTIONS and CORS
Section titled “OPTIONS and CORS”OPTIONS is handled in the method-dispatch layer before your OPTIONS handler or before middleware when shortcuts apply.
CORS preflight when all hold: method is OPTIONS, path matched, pipeline has a CORS policy, request includes Origin and Access-Control-Request-Method. Answered before explicit OPTIONS handlers or middleware.
| Outcome | Status | Body |
|---|---|---|
| Origin allowed | 204 | empty + CORS headers |
| Origin denied | 204 | empty + Allow only (no Access-Control-Allow-Origin) |
Auto-Allow OPTIONS (non-preflight, no explicit OPTIONS handler): 204 with Allow listing registered methods plus HEAD when GET exists, plus OPTIONS.
Register host.http.options(…) or @Options when you need custom OPTIONS behavior.
See CORS overview for policy registration.
Related
Section titled “Related”- Custom 404 responses
- Middleware: ordering after a match
- HTTP contracts: parsing after route match