# flare.http.router

> A module of flare_mlake's API.

HTTP request router with method dispatch + path parameters.

A ``Router`` is a ``Handler`` that dispatches each request to a
per-(method, path) inner handler. It supports:

- **Literal segments**: ``"/users"`` matches exactly ``/users``.
- **Parameter segments**: ``":id"`` matches one segment of any non-empty
  value; the captured value lands in ``req.params[name]``.
- **Wildcard tail**: a final segment ``"*"`` matches the rest of the
  path (captured as ``req.param("*")``, including path separators).
- **Method dispatch**: ``get`` / ``post`` / ``put`` / ``patch`` /
  ``delete`` / ``head`` register one handler per (method, path) pair.

Unknown paths return **404 Not Found**; known paths called with the
wrong method return **405 Method Not Allowed** with a synthesised
``Allow:`` header listing the supported methods.

Sub-router mounting (``mount(prefix, sub)``) attaches a whole nested
``Router`` under a literal path prefix (e.g. ``/api/v1``). The mounted
router is owned by value behind the same ``ArcPointer`` refcount the
struct-handler registry uses, so Router copies (one per worker) share
the mounted subtree without double-freeing it. A mounted prefix owns
its entire subtree: direct routes registered on the parent take
priority, and any unmatched request whose path starts with the prefix
is delegated (with the prefix stripped) to the sub-router, which runs
its own method dispatch and 404/405 synthesis.

Example:

```mojo
from flare.http import Router, Request, Response, ok, not_found

def home(req: Request) raises -> Response:
    return ok("home")

def get_user(req: Request) raises -> Response:
    return ok("user " + req.param("id"))

def main() raises:
    var r = Router()
    r.get("/", home)
    r.get("/users/:id", get_user)

    # `r` is a Handler; pass it to HttpServer.serve.
```

This first release uses a simple runtime match (linear scan per depth
plus a per-entry segment compare). A compile-time trie lives on the
roadmap; the public Router API will not change when the trie
lands, only the internal representation.

## Structs

### `Router`

```mojo
struct Router
```

HTTP router with method dispatch, path parameters, and nesting.

Accepts both plain ``def(Request) raises -> Response`` functions
(wrapped internally in ``FnHandler``) **and** arbitrary
``H: Handler & Copyable`` structs (boxed via ``_StructHandler``
with monomorphised serve / destroy thunks).
Use the latter to register
``Extracted[H]()``, app-state-bearing handlers, middleware
wrappers, and any other stateful Handler.

Routes are stored as ``(method, compiled-segments,
handler-kind, handler-index)`` quadruples; ``handler-kind``
selects ``_handlers`` (FnHandler list) or ``_struct_handlers``
(boxed Handler structs) for the actual call site.

Example:
```mojo
var r = Router()
r.get("/", home) # def(Request)
r.get("/users/:id", Extracted[GetUser]()) # Handler struct
```

Implements: `Copyable`, `Defaultable`, `Handler`, `Movable`

#### `BodyType`

```mojo
comptime BodyType = InlineBody
```

The ``Body`` impl this handler authors its response with.

Defaults to :struct:`InlineBody` so plain handlers that return
``Response`` conform without declaring it. Override in a handler that
returns a typed ``ResponseImpl[SomeBody]``.

#### `__init__`

```mojo
def __init__(out self)
```

Create an empty router (no routes).

#### `get`

```mojo
def get(mut self, path: String, handler: def(Request) raises thin -> Response)
```

Register ``handler`` for ``GET path``.

Args:

- `path`: Route pattern (e.g. ``"/users/:id"``).
- `handler`: The function to call on a match.

```mojo
def get[H: Handler & Copyable](mut self, path: String, var handler: H)
```

Register ``handler`` (a Handler struct) for ``GET path``.

``H`` is type-erased into ``_StructHandler`` via heap
allocation + monomorphised serve / destroy thunks; the
per-request dispatch is a direct call through the cached
thunk pointer with no trait-table lookup.

Use this overload to register ``Extracted[H]()``, app-state
handlers, middleware-wrapped handlers, and any user-defined
Handler struct. The ``def(Request) raises -> Response``
overload above continues to work unchanged.

Args:

- `path`: Route pattern (e.g. ``"/users/:id"``).
- `handler`: A ``Handler & Copyable`` instance;
         ownership transfers into the Router (the
         Router owns the heap allocation and frees it
         in its destructor).

#### `post`

```mojo
def post(mut self, path: String, handler: def(Request) raises thin -> Response)
```

Register ``handler`` for ``POST path``.

```mojo
def post[H: Handler & Copyable](mut self, path: String, var handler: H)
```

Register ``handler`` (a Handler struct) for ``POST path``. See ``get[H]`` for the type-erasure shape.

#### `put`

```mojo
def put(mut self, path: String, handler: def(Request) raises thin -> Response)
```

Register ``handler`` for ``PUT path``.

```mojo
def put[H: Handler & Copyable](mut self, path: String, var handler: H)
```

Register ``handler`` (a Handler struct) for ``PUT path``. See ``get[H]`` for the type-erasure shape.

#### `patch`

```mojo
def patch(mut self, path: String, handler: def(Request) raises thin -> Response)
```

Register ``handler`` for ``PATCH path``.

```mojo
def patch[H: Handler & Copyable](mut self, path: String, var handler: H)
```

Register ``handler`` (a Handler struct) for ``PATCH path``. See ``get[H]`` for the type-erasure shape.

#### `delete`

```mojo
def delete(mut self, path: String, handler: def(Request) raises thin -> Response)
```

Register ``handler`` for ``DELETE path``.

```mojo
def delete[H: Handler & Copyable](mut self, path: String, var handler: H)
```

Register ``handler`` (a Handler struct) for ``DELETE path``. See ``get[H]`` for the type-erasure shape.

#### `head`

```mojo
def head(mut self, path: String, handler: def(Request) raises thin -> Response)
```

Register ``handler`` for ``HEAD path``.

```mojo
def head[H: Handler & Copyable](mut self, path: String, var handler: H)
```

Register ``handler`` (a Handler struct) for ``HEAD path``. See ``get[H]`` for the type-erasure shape.

#### `options`

```mojo
def options(mut self, path: String, handler: def(Request) raises thin -> Response)
```

Register ``handler`` for ``OPTIONS path``.

```mojo
def options[H: Handler & Copyable](mut self, path: String, var handler: H)
```

Register ``handler`` (a Handler struct) for ``OPTIONS path``. See ``get[H]`` for the type-erasure shape.

#### `trace`

```mojo
def trace(mut self, path: String, handler: def(Request) raises thin -> Response)
```

Register ``handler`` for ``TRACE path``.

```mojo
def trace[H: Handler & Copyable](mut self, path: String, var handler: H)
```

Register ``handler`` (a Handler struct) for ``TRACE path``. See ``get[H]`` for the type-erasure shape.

#### `connect`

```mojo
def connect(mut self, path: String, handler: def(Request) raises thin -> Response)
```

Register ``handler`` for ``CONNECT path``.

```mojo
def connect[H: Handler & Copyable](mut self, path: String, var handler: H)
```

Register ``handler`` (a Handler struct) for ``CONNECT path``. See ``get[H]`` for the type-erasure shape.

#### `fallback`

```mojo
def fallback(mut self, handler: def(Request) raises thin -> Response)
```

Set a custom fallback handler.

Invoked when no registered route matched and no mounted
sub-router claimed the path. Replaces the default 404 body
(the 405 path for a known path under other methods still
fires first). Registering twice keeps the last handler.

#### `mount`

```mojo
def mount(mut self, prefix: String, var sub: Self)
```

Mount ``sub`` under the literal path ``prefix``.

Every request whose path starts with ``prefix`` (and which no
directly-registered route on this Router already handled) is
delegated to ``sub`` with ``prefix`` stripped, so ``sub`` sees
paths relative to its mount point. ``sub`` performs its own
method dispatch and 404/405 synthesis.

The sub-router is boxed into the shared struct-handler registry
(heap-allocated, monomorphised destroy thunk) so it is owned by
value and freed exactly once on the last Router drop -- the same
ownership model as struct handlers.

Args:

- `prefix`: A literal path prefix, e.g. ``"/api/v1"``. Parameter
        (``:id``) and wildcard (``*``) segments are rejected.
- `sub`: The sub-router to mount; ownership transfers in.

#### `route_count`

```mojo
def route_count(self) -> Int
```

Number of registered top-level routes (excludes mounts).

#### `route_method`

```mojo
def route_method(self, i: Int) -> String
```

HTTP method of route ``i`` (uppercase, e.g. ``GET``).

#### `route_openapi_template`

```mojo
def route_openapi_template(self, i: Int) -> String
```

Route ``i``'s path as an OpenAPI template: ``:id`` -> ``{id}``, wildcard ``*`` -> ``{path}`` (``/`` for the empty root).

#### `route_path_params`

```mojo
def route_path_params(self, i: Int) -> List[String]
```

Names of route ``i``'s path parameters (``:name`` segments).

#### `serve`

```mojo
def serve(self, req: Request) -> Response
```

Dispatch ``req`` to the matching handler.

Returns the handler's response, or a 404 / 405 if no
route matches.
