Skip to content

Routing behavior

HTTP path matching, 404 and 405, HEAD fallback, OPTIONS, CORS preflight, wildcards, and URL decoding after host.build().

AI generated, pending review Updated 10 days ago · Flare 0.3

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.

Each registered path becomes one pipeline: a single match target shared by every HTTP method you registered on that path. On each request, Flare:

  1. Matches the request pathname (no query string).
  2. Resolves the HTTP method (including HEAD fallback and OPTIONS shortcuts).
  3. Extracts route parameters when a handler will run.
  4. 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.

RegistrationEffective 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 formMeaningSpecificity 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.

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.

Flare rejects the request with 400 when the inbound pathname fails:

RuleExample invalidExample valid
Must start with /users, ""/users
No trailing / except root/users//users, /
No empty segments (//)/a//b/a/b
At most 8192 charactersa 9000-character pathnameany ordinary URL path

/users/ does not fall through to /users. No middleware or handler runs for invalid pathnames.

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.

Flare dispatches GET, POST, PUT, PATCH, DELETE, HEAD, and OPTIONS. Any other method on a matched path returns 405.

FieldValue
Status404
BodyPlain text Not Found

This is not routed through host.http.error(). For a custom 404, see Custom 404 responses.

FieldValue
Status405
BodyPlain text Method Not Allowed
AllowMethods 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.

When the request method is HEAD:

  1. If an explicit HEAD handler is registered, it runs.
  2. Otherwise, if a GET handler exists, Flare runs GET and returns the same status and headers with a null body.

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.

OutcomeStatusBody
Origin allowed204empty + CORS headers
Origin denied204empty + 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.