Skip to content

Routers, Blueprints & Views

The route-group primitives a project is structured with.

Router

High-performance radix-tree router with a decorator-based route API.

Usage::

from veloce import Router, Veloce

api = Router(prefix="/api")

@api.get("/items/{item_id:int}")
async def get_item(item_id: int):
    return {"item_id": item_id}

app = Veloce()
app.include_router(api)

add_route

add_route(path: Annotated[str, Doc('URL path template, including `{param}` / `{param:converter}` placeholders.')], handler: Annotated[RouteHandler, Doc('Async or sync callable invoked when the route matches.')], methods: Annotated[list[str], Doc('HTTP methods this handler serves (uppercased internally).')], dependencies: Annotated[list[Any] | None, Doc('Dependencies run for this route, appended after the router-level ones.')] = None, response_model: Annotated[Any, _DOC_RESPONSE_MODEL] = _INFER_RESPONSE_MODEL, tags: Annotated[list[str] | None, Doc('OpenAPI tags for this route, combined with the router-level tags.')] = None, summary: Annotated[str | None, Doc('Short OpenAPI summary for this operation.')] = None, name: Annotated[str | None, Doc("Endpoint name for `url_for` reverse lookup; defaults to the handler's name.")] = None, description: Annotated[str | None, Doc("OpenAPI description; defaults to the handler's docstring.")] = None, deprecated: Annotated[bool, Doc('Mark the operation as deprecated in the OpenAPI document.')] = False, response_description: Annotated[str, Doc('Description of the successful response in the OpenAPI document.')] = MSG_SUCCESSFUL_RESPONSE, status_code: Annotated[int, Doc('Default HTTP status code for a successful response.')] = HTTP_200_OK, response_class: Annotated[Any, Doc('Response class for this route, overriding the router and framework defaults.')] = None, response_model_include: Annotated[set[str] | None, Doc('Fields to include when serializing the response model.')] = None, response_model_exclude: Annotated[set[str] | None, Doc('Fields to exclude when serializing the response model.')] = None, response_model_exclude_unset: Annotated[bool, Doc('Omit fields left unset on the response model from the serialized output.')] = False, response_model_exclude_defaults: Annotated[bool, Doc('Omit fields equal to their default on the response model from the serialized output.')] = False, response_model_by_alias: Annotated[bool, Doc('Serialize the response model using field aliases instead of attribute names.')] = False, response_model_exclude_none: Annotated[bool, Doc('Omit fields whose value is `None` from the serialized response model.')] = False, include_in_schema: Annotated[bool, Doc('Register the route but omit it from the generated OpenAPI document when False.')] = True, responses: Annotated[dict[int, dict[str, Any]] | None, Doc('Additional OpenAPI responses for this route, overlaid on the router-level ones.')] = None, operation_id: Annotated[str | None, Doc('Explicit OpenAPI `operationId`; defaults to the route name.')] = None, openapi_extra: Annotated[dict[str, Any] | None, Doc("Arbitrary dict deep-merged into this route's OpenAPI operation object.")] = None, defaults: Annotated[dict[str, Any] | None, Doc('Fixed values merged into the path params at dispatch without overriding URL-matched ones.')] = None, callbacks: Annotated[dict[str, Any] | None, Doc("OpenAPI Callback objects emitted verbatim into the operation's `callbacks` field.")] = None, strict_slashes: Annotated[bool | None, Doc('When False, match both slashed and unslashed forms; `None` defers to the app policy.')] = None, subdomain: Annotated[str | None, Doc('Constrain the route to a subdomain of `SERVER_NAME`; `*` matches any non-apex subdomain.')] = None, host: Annotated[str | None, Doc('Constrain the route to an exact `Host` header value (case-insensitive).')] = None, expose_as_mcp_tool: Annotated[bool, Doc('Expose the route as an MCP tool in the contrib MCP registry.')] = False, mcp_description: Annotated[str | None, Doc("LLM-facing description for the route's MCP tool, required when exposed as one.")] = None, expose_as_mcp_resource: Annotated[bool, Doc('Expose the read-only route as an MCP resource in the contrib MCP registry.')] = False, mcp_resource_uri: Annotated[str | None, _DOC_MCP_RESOURCE_URI] = None, mcp_resource_mime_type: Annotated[str | None, _DOC_MCP_RESOURCE_MIME_TYPE] = None, mcp_meta: Annotated[dict[str, Any] | None, _DOC_MCP_META] = None, mcp_resource_size: Annotated[int | None, Doc("Size in bytes advertised for the route's MCP resource.")] = None, mcp_resource_annotations: Annotated[dict[str, Any] | None, Doc("Annotations (audience, priority) advertised for the route's MCP resource.")] = None, mcp_scopes: Annotated[Sequence[str] | None, Doc('Authorization scopes required to call this route over MCP.')] = None, mcp_icons: Annotated[Sequence[Any] | None, Doc('Optional MCP `Icon` objects a client may render next to the tool/resource.')] = None, mcp_task_support: Annotated[bool, _DOC_MCP_TASK_SUPPORT] = False, exclude_middleware: Annotated[Sequence[str | type] | None, _DOC_EXCLUDE_MIDDLEWARE] = None, stream: Annotated[bool, _DOC_STREAM] = False) -> None

Register a route in the radix tree.

strict_slashes=False matches both the slashed and unslashed forms without redirecting. None (default) defers to the app's global redirect_slashes policy.

subdomain="api" constrains the route to requests whose Host header matches {subdomain}.{app.config["SERVER_NAME"]}. The match is exact (no globbing); for wildcard subdomain matching use subdomain="*" and inspect request.subdomain inside the handler.

match

match(method: str, path: str) -> RouteMatch | None

Match a request path. Static map, then radix tree, then regex.

O(1) for a literal path (the static map), else O(k) on the tree where k = path depth. The regex fallback runs only when the tree misses and regex routes are registered; the tree always wins over regex when both could match.

get_allowed_methods

get_allowed_methods(path: str) -> list[str]

Get allowed methods for a path (for 405 responses).

Unions the methods reachable through the radix tree AND any regex routes that match the same path, so a path served by a tree handler on one method and a regex handler on another reports both for 405/OPTIONS. Tree methods are listed first (dispatch precedence); duplicates removed.

route

route(path: Annotated[str, Doc('URL path template, including `{param}` / `{param:converter}` placeholders.')], methods: Annotated[list[str] | None, Doc('HTTP methods this handler serves; defaults to `GET`.')] = None, dependencies: Annotated[list[Any] | None, Doc('Dependencies run for this route, appended after the router-level ones.')] = None, response_model: Annotated[Any, _DOC_RESPONSE_MODEL] = _INFER_RESPONSE_MODEL, tags: Annotated[list[str] | None, Doc('OpenAPI tags for this route, combined with the router-level tags.')] = None, summary: Annotated[str | None, Doc('Short OpenAPI summary for this operation.')] = None, name: Annotated[str | None, Doc("Endpoint name for `url_for` reverse lookup; defaults to the handler's name.")] = None, description: Annotated[str | None, Doc("OpenAPI description; defaults to the handler's docstring.")] = None, deprecated: Annotated[bool, Doc('Mark the operation as deprecated in the OpenAPI document.')] = False, response_description: Annotated[str, Doc('Description of the successful response in the OpenAPI document.')] = MSG_SUCCESSFUL_RESPONSE, status_code: Annotated[int, Doc('Default HTTP status code for a successful response.')] = HTTP_200_OK, response_class: Annotated[Any, Doc('Response class for this route, overriding the router and framework defaults.')] = None, response_model_include: Annotated[set[str] | None, Doc('Fields to include when serializing the response model.')] = None, response_model_exclude: Annotated[set[str] | None, Doc('Fields to exclude when serializing the response model.')] = None, response_model_exclude_unset: Annotated[bool, Doc('Omit fields left unset on the response model from the serialized output.')] = False, response_model_exclude_defaults: Annotated[bool, Doc('Omit fields equal to their default on the response model from the serialized output.')] = False, response_model_by_alias: Annotated[bool, Doc('Serialize the response model using field aliases instead of attribute names.')] = False, response_model_exclude_none: Annotated[bool, Doc('Omit fields whose value is `None` from the serialized response model.')] = False, include_in_schema: Annotated[bool, Doc('Register the route but omit it from the generated OpenAPI document when False.')] = True, responses: Annotated[dict[int, dict[str, Any]] | None, Doc('Additional OpenAPI responses for this route, overlaid on the router-level ones.')] = None, operation_id: Annotated[str | None, Doc('Explicit OpenAPI `operationId`; defaults to the route name.')] = None, openapi_extra: Annotated[dict[str, Any] | None, Doc("Arbitrary dict deep-merged into this route's OpenAPI operation object.")] = None, defaults: Annotated[dict[str, Any] | None, Doc('Fixed values merged into the path params at dispatch without overriding URL-matched ones.')] = None, callbacks: Annotated[dict[str, Any] | None, Doc("OpenAPI Callback objects emitted verbatim into the operation's `callbacks` field.")] = None, strict_slashes: Annotated[bool | None, Doc('When False, match both slashed and unslashed forms; `None` defers to the app policy.')] = None, subdomain: Annotated[str | None, Doc('Constrain the route to a subdomain of `SERVER_NAME`; `*` matches any non-apex subdomain.')] = None, host: Annotated[str | None, Doc('Constrain the route to an exact `Host` header value (case-insensitive).')] = None, expose_as_mcp_tool: Annotated[bool, Doc('Expose the route as an MCP tool in the contrib MCP registry.')] = False, mcp_description: Annotated[str | None, Doc("LLM-facing description for the route's MCP tool, required when exposed as one.")] = None, expose_as_mcp_resource: Annotated[bool, Doc('Expose the read-only route as an MCP resource in the contrib MCP registry.')] = False, mcp_resource_uri: Annotated[str | None, _DOC_MCP_RESOURCE_URI] = None, mcp_resource_mime_type: Annotated[str | None, _DOC_MCP_RESOURCE_MIME_TYPE] = None, mcp_meta: Annotated[dict[str, Any] | None, _DOC_MCP_META] = None, mcp_resource_size: Annotated[int | None, Doc("Size in bytes advertised for the route's MCP resource.")] = None, mcp_resource_annotations: Annotated[dict[str, Any] | None, Doc("Annotations (audience, priority) advertised for the route's MCP resource.")] = None, mcp_scopes: Annotated[Sequence[str] | None, Doc('Authorization scopes required to call this route over MCP.')] = None, mcp_icons: Annotated[Sequence[Any] | None, Doc('Optional MCP `Icon` objects a client may render next to the tool/resource.')] = None, mcp_task_support: Annotated[bool, _DOC_MCP_TASK_SUPPORT] = False, exclude_middleware: Annotated[Sequence[str | type] | None, _DOC_EXCLUDE_MIDDLEWARE] = None, stream: Annotated[bool, _DOC_STREAM] = False) -> Callable

Register a route for any set of HTTP methods.

exclude_middleware=["CSRFMiddleware"] opts this route out of the named middleware (matched against each middleware's name), so a webhook or health-check route can skip CSRF, auth, or rate limiting without forking the middleware. Routes that declare no exclusions pay no extra per-request cost.

get

get(path: str, **kwargs: Any) -> Callable

GET route decorator. Safe and idempotent - RFC 9110 Sec. 9.3.1.

post

post(path: str, **kwargs: Any) -> Callable

POST route decorator - RFC 9110 Sec. 9.3.3.

put

put(path: str, **kwargs: Any) -> Callable

PUT route decorator. Idempotent - RFC 9110 Sec. 9.3.4.

patch

patch(path: str, **kwargs: Any) -> Callable

PATCH route decorator - RFC 5789.

delete

delete(path: str, **kwargs: Any) -> Callable

DELETE route decorator. Idempotent - RFC 9110 Sec. 9.3.5.

head

head(path: str, **kwargs: Any) -> Callable

HEAD route decorator. Like GET with no body - RFC 9110 Sec. 9.3.2.

options

options(path: str, **kwargs: Any) -> Callable

OPTIONS route decorator - RFC 9110 Sec. 9.3.7.

trace

trace(path: str, **kwargs: Any) -> Callable

TRACE route decorator - RFC 9110 Sec. 9.3.8.

query

query(path: str, **kwargs: Any) -> Callable

QUERY route decorator - RFC 10008.

QUERY is safe and idempotent like GET but carries a request body like POST, for read-only operations whose parameters do not fit a URL (search, filtering, paging). The handler reads the body exactly as a POST handler does (request.get_json() / a body model parameter).

websocket

websocket(path: Annotated[str, Doc('URL path template for the WebSocket route, including `{param}` placeholders.')]) -> Callable

Register a WebSocket route via decorator.

websocket_listener

websocket_listener(path: str, *, receive: str = 'json', send: str = 'json', on_connect: RouteHandler | Callable[..., Any] | None = None, on_disconnect: RouteHandler | Callable[..., Any] | None = None) -> Callable

Register a WebSocket route wrapping a per-message callback.

The decorated callback handles one message at a time; the framework owns the accept handshake, the receive loop, and the clean close on disconnect. The callback is called as cb(data), or cb(ws, data) when its first parameter is named ws/socket (or it takes two positional parameters). Returning a non-None value sends it back in send mode; returning None sends nothing.

receive/send select the codec ("json" default, or "text" / "bytes"). on_connect(ws) runs after accept; on_disconnect(ws) always runs when the loop ends, including on peer disconnect. Sync callbacks and hooks are offloaded to the executor.

Usage::

@app.websocket_listener("/echo")
async def echo(data):
    return data

For full control over the handshake and loop use @app.websocket.

add_websocket_route

add_websocket_route(path: Annotated[str, Doc('URL path template for the WebSocket route, including `{param}` placeholders.')], handler: Annotated[RouteHandler, Doc('Callable invoked with the accepted WebSocket connection when the route matches.')]) -> None

Register a WebSocket route imperatively (ASGI shape).

The non-decorator form of @app.websocket(path).

add_api_websocket_route

add_api_websocket_route(path: str, endpoint: RouteHandler, name: str | None = None) -> None

Register an imperative WebSocket route, mirroring add_api_route.

The non-decorator form of @app.websocket(path). name, when given, registers the route for reverse lookup so app.url_for(name) resolves to its path.

add_api_route

add_api_route(path: str, endpoint: RouteHandler, *, methods: list[str] | None = None, **kwargs: Any) -> None

Register a route imperatively.

The non-decorator form: the handler argument is named endpoint here and forwarded to add_route (where it is handler). All route kwargs - response_model, tags, dependencies, status_code, openapi_extra, ... - pass straight through. Defaults to ["GET"] when methods is omitted.

url_for

url_for(name: str, /, **path_params: Any) -> str

Reverse URL lookup by route name (url_for).

Substitutes each {name} placeholder in the registered template with the matching path_params kwarg. Underscore-prefixed kwargs are control parameters (convention):

  • _external=True - return an absolute URL. Uses app.config["SERVER_NAME"] when set, otherwise falls back to localhost. Caller should override _scheme/_host for anything more specific.
  • _scheme="https" - override scheme on the absolute URL.
  • _host="example.com" - override host on the absolute URL.
  • _anchor="section" - append #section.
  • Any other unmatched kwarg becomes a query-string parameter.

iter_routes

iter_routes(*, include_hidden: bool = False) -> list[tuple[str, str, RouteInfo]]

Return every registered route as (method, path, info).

app.routes is a summary view: six fields of RouteInfo's full record, which is enough to render a route table and not enough for anything that inspects a route. This returns the records themselves, so response models, dependencies, security requirements and the rest are reachable without touching private state.

Hidden routes - WebSocket routes and those registered include_in_schema=False - are omitted unless include_hidden is set; the default is the schema-visible set.

Usage::

for method, path, info in app.iter_routes():
    if info.response_model is not None:
        print(method, path, info.response_model)

include_router

include_router(router: Router, prefix: str = '') -> None

Include another router (a sub-router with its own prefix, tags, and hooks).

APIRouter module-attribute

APIRouter = Router

Blueprint

Bases: Router

Deferred-registration route collection.

Usage::

from veloce import Blueprint, Veloce

bp = Blueprint("admin", url_prefix="/admin")

@bp.get("/ping")
async def ping():
    return {"ok": True}

app = Veloce()
app.register_blueprint(bp)  # serves GET /admin/ping

add_route

add_route(path: Annotated[str, Doc('URL path template, including `{param}` / `{param:converter}` placeholders.')], handler: Annotated[RouteHandler, Doc('Async or sync callable invoked when the route matches.')], methods: Annotated[list[str], Doc('HTTP methods this handler serves (uppercased internally).')], dependencies: Annotated[list[Any] | None, Doc('Dependencies run for this route, appended after the router-level ones.')] = None, response_model: Annotated[Any, _DOC_RESPONSE_MODEL] = _INFER_RESPONSE_MODEL, tags: Annotated[list[str] | None, Doc('OpenAPI tags for this route, combined with the router-level tags.')] = None, summary: Annotated[str | None, Doc('Short OpenAPI summary for this operation.')] = None, name: Annotated[str | None, Doc("Endpoint name for `url_for` reverse lookup; defaults to the handler's name.")] = None, description: Annotated[str | None, Doc("OpenAPI description; defaults to the handler's docstring.")] = None, deprecated: Annotated[bool, Doc('Mark the operation as deprecated in the OpenAPI document.')] = False, response_description: Annotated[str, Doc('Description of the successful response in the OpenAPI document.')] = MSG_SUCCESSFUL_RESPONSE, status_code: Annotated[int, Doc('Default HTTP status code for a successful response.')] = HTTP_200_OK, response_class: Annotated[Any, Doc('Response class for this route, overriding the router and framework defaults.')] = None, response_model_include: Annotated[set[str] | None, Doc('Fields to include when serializing the response model.')] = None, response_model_exclude: Annotated[set[str] | None, Doc('Fields to exclude when serializing the response model.')] = None, response_model_exclude_unset: Annotated[bool, Doc('Omit fields left unset on the response model from the serialized output.')] = False, response_model_exclude_defaults: Annotated[bool, Doc('Omit fields equal to their default on the response model from the serialized output.')] = False, response_model_by_alias: Annotated[bool, Doc('Serialize the response model using field aliases instead of attribute names.')] = False, response_model_exclude_none: Annotated[bool, Doc('Omit fields whose value is `None` from the serialized response model.')] = False, include_in_schema: Annotated[bool, Doc('Register the route but omit it from the generated OpenAPI document when False.')] = True, responses: Annotated[dict[int, dict[str, Any]] | None, Doc('Additional OpenAPI responses for this route, overlaid on the router-level ones.')] = None, operation_id: Annotated[str | None, Doc('Explicit OpenAPI `operationId`; defaults to the route name.')] = None, openapi_extra: Annotated[dict[str, Any] | None, Doc("Arbitrary dict deep-merged into this route's OpenAPI operation object.")] = None, defaults: Annotated[dict[str, Any] | None, Doc('Fixed values merged into the path params at dispatch without overriding URL-matched ones.')] = None, callbacks: Annotated[dict[str, Any] | None, Doc("OpenAPI Callback objects emitted verbatim into the operation's `callbacks` field.")] = None, strict_slashes: Annotated[bool | None, Doc('When False, match both slashed and unslashed forms; `None` defers to the app policy.')] = None, subdomain: Annotated[str | None, Doc('Constrain the route to a subdomain of `SERVER_NAME`; `*` matches any non-apex subdomain.')] = None, host: Annotated[str | None, Doc('Constrain the route to an exact `Host` header value (case-insensitive).')] = None, expose_as_mcp_tool: Annotated[bool, Doc('Expose the route as an MCP tool in the contrib MCP registry.')] = False, mcp_description: Annotated[str | None, Doc("LLM-facing description for the route's MCP tool, required when exposed as one.")] = None, expose_as_mcp_resource: Annotated[bool, Doc('Expose the read-only route as an MCP resource in the contrib MCP registry.')] = False, mcp_resource_uri: Annotated[str | None, _DOC_MCP_RESOURCE_URI] = None, mcp_resource_mime_type: Annotated[str | None, _DOC_MCP_RESOURCE_MIME_TYPE] = None, mcp_meta: Annotated[dict[str, Any] | None, _DOC_MCP_META] = None, mcp_resource_size: Annotated[int | None, Doc("Size in bytes advertised for the route's MCP resource.")] = None, mcp_resource_annotations: Annotated[dict[str, Any] | None, Doc("Annotations (audience, priority) advertised for the route's MCP resource.")] = None, mcp_scopes: Annotated[Sequence[str] | None, Doc('Authorization scopes required to call this route over MCP.')] = None, mcp_icons: Annotated[Sequence[Any] | None, Doc('Optional MCP `Icon` objects a client may render next to the tool/resource.')] = None, mcp_task_support: Annotated[bool, _DOC_MCP_TASK_SUPPORT] = False, exclude_middleware: Annotated[Sequence[str | type] | None, _DOC_EXCLUDE_MIDDLEWARE] = None, stream: Annotated[bool, _DOC_STREAM] = False) -> None

Register a route in the radix tree.

strict_slashes=False matches both the slashed and unslashed forms without redirecting. None (default) defers to the app's global redirect_slashes policy.

subdomain="api" constrains the route to requests whose Host header matches {subdomain}.{app.config["SERVER_NAME"]}. The match is exact (no globbing); for wildcard subdomain matching use subdomain="*" and inspect request.subdomain inside the handler.

match

match(method: str, path: str) -> RouteMatch | None

Match a request path. Static map, then radix tree, then regex.

O(1) for a literal path (the static map), else O(k) on the tree where k = path depth. The regex fallback runs only when the tree misses and regex routes are registered; the tree always wins over regex when both could match.

get_allowed_methods

get_allowed_methods(path: str) -> list[str]

Get allowed methods for a path (for 405 responses).

Unions the methods reachable through the radix tree AND any regex routes that match the same path, so a path served by a tree handler on one method and a regex handler on another reports both for 405/OPTIONS. Tree methods are listed first (dispatch precedence); duplicates removed.

get

get(path: str, **kwargs: Any) -> Callable

GET route decorator. Safe and idempotent - RFC 9110 Sec. 9.3.1.

post

post(path: str, **kwargs: Any) -> Callable

POST route decorator - RFC 9110 Sec. 9.3.3.

put

put(path: str, **kwargs: Any) -> Callable

PUT route decorator. Idempotent - RFC 9110 Sec. 9.3.4.

patch

patch(path: str, **kwargs: Any) -> Callable

PATCH route decorator - RFC 5789.

delete

delete(path: str, **kwargs: Any) -> Callable

DELETE route decorator. Idempotent - RFC 9110 Sec. 9.3.5.

head

head(path: str, **kwargs: Any) -> Callable

HEAD route decorator. Like GET with no body - RFC 9110 Sec. 9.3.2.

options

options(path: str, **kwargs: Any) -> Callable

OPTIONS route decorator - RFC 9110 Sec. 9.3.7.

trace

trace(path: str, **kwargs: Any) -> Callable

TRACE route decorator - RFC 9110 Sec. 9.3.8.

query

query(path: str, **kwargs: Any) -> Callable

QUERY route decorator - RFC 10008.

QUERY is safe and idempotent like GET but carries a request body like POST, for read-only operations whose parameters do not fit a URL (search, filtering, paging). The handler reads the body exactly as a POST handler does (request.get_json() / a body model parameter).

websocket

websocket(path: Annotated[str, Doc('URL path template for the WebSocket route, including `{param}` placeholders.')]) -> Callable

Register a WebSocket route via decorator.

websocket_listener

websocket_listener(path: str, *, receive: str = 'json', send: str = 'json', on_connect: RouteHandler | Callable[..., Any] | None = None, on_disconnect: RouteHandler | Callable[..., Any] | None = None) -> Callable

Register a WebSocket route wrapping a per-message callback.

The decorated callback handles one message at a time; the framework owns the accept handshake, the receive loop, and the clean close on disconnect. The callback is called as cb(data), or cb(ws, data) when its first parameter is named ws/socket (or it takes two positional parameters). Returning a non-None value sends it back in send mode; returning None sends nothing.

receive/send select the codec ("json" default, or "text" / "bytes"). on_connect(ws) runs after accept; on_disconnect(ws) always runs when the loop ends, including on peer disconnect. Sync callbacks and hooks are offloaded to the executor.

Usage::

@app.websocket_listener("/echo")
async def echo(data):
    return data

For full control over the handshake and loop use @app.websocket.

add_websocket_route

add_websocket_route(path: Annotated[str, Doc('URL path template for the WebSocket route, including `{param}` placeholders.')], handler: Annotated[RouteHandler, Doc('Callable invoked with the accepted WebSocket connection when the route matches.')]) -> None

Register a WebSocket route imperatively (ASGI shape).

The non-decorator form of @app.websocket(path).

add_api_websocket_route

add_api_websocket_route(path: str, endpoint: RouteHandler, name: str | None = None) -> None

Register an imperative WebSocket route, mirroring add_api_route.

The non-decorator form of @app.websocket(path). name, when given, registers the route for reverse lookup so app.url_for(name) resolves to its path.

add_api_route

add_api_route(path: str, endpoint: RouteHandler, *, methods: list[str] | None = None, **kwargs: Any) -> None

Register a route imperatively.

The non-decorator form: the handler argument is named endpoint here and forwarded to add_route (where it is handler). All route kwargs - response_model, tags, dependencies, status_code, openapi_extra, ... - pass straight through. Defaults to ["GET"] when methods is omitted.

url_for

url_for(name: str, /, **path_params: Any) -> str

Reverse URL lookup by route name (url_for).

Substitutes each {name} placeholder in the registered template with the matching path_params kwarg. Underscore-prefixed kwargs are control parameters (convention):

  • _external=True - return an absolute URL. Uses app.config["SERVER_NAME"] when set, otherwise falls back to localhost. Caller should override _scheme/_host for anything more specific.
  • _scheme="https" - override scheme on the absolute URL.
  • _host="example.com" - override host on the absolute URL.
  • _anchor="section" - append #section.
  • Any other unmatched kwarg becomes a query-string parameter.

iter_routes

iter_routes(*, include_hidden: bool = False) -> list[tuple[str, str, RouteInfo]]

Return every registered route as (method, path, info).

app.routes is a summary view: six fields of RouteInfo's full record, which is enough to render a route table and not enough for anything that inspects a route. This returns the records themselves, so response models, dependencies, security requirements and the rest are reachable without touching private state.

Hidden routes - WebSocket routes and those registered include_in_schema=False - are omitted unless include_hidden is set; the default is the schema-visible set.

Usage::

for method, path, info in app.iter_routes():
    if info.response_model is not None:
        print(method, path, info.response_model)

include_router

include_router(router: Router, prefix: str = '') -> None

Include another router (a sub-router with its own prefix, tags, and hooks).

route

route(*args: Any, **kwargs: Any) -> Any

Declare a route, refusing a name that would break the endpoint split.

On the decorator rather than on add_route, because those are the two different callers: every user-facing shortcut (get, post, ...) reaches route, while _readd_route calls add_route directly with an endpoint it has already composed - "child.handler" - which this would otherwise reject as the framework re-registers its own routes.

The name is recovered by binding against Router.route's own signature rather than by indexing a position: it enumerates about forty options, and one more should not silently move which argument is read.

before_request

before_request(func: Callable) -> Callable

Register a function to run before each blueprint request.

Fires only for requests that match a route declared on this blueprint. Use app.before_request for app-wide hooks.

after_request

after_request(func: Callable) -> Callable

Register a function to run after each blueprint request.

teardown_request

teardown_request(func: Callable) -> Callable

Run after blueprint-routed request teardown, with optional exc.

errorhandler

errorhandler(exc_class_or_status: type | int) -> Callable

Blueprint-scoped error handler.

Matches app.errorhandler semantics: integer keys go to the status-code table, classes go to the MRO-matched exception table. The handler runs for exceptions raised by blueprint handlers; app-level handlers act as fallback (registration order: blueprint wins on direct match).

url_value_preprocessor

url_value_preprocessor(func: Callable) -> Callable

Register a fn(endpoint, values) URL preprocessor on this blueprint.

Mirrors @app.url_value_preprocessor - runs after route match for blueprint-routed requests, mutating values in place. Use to pop a path-param into g (e.g. a lang segment) before the handler sees it.

url_defaults

url_defaults(func: Callable) -> Callable

Register a fn(endpoint, values) URL-defaults injector for url_for.

Mirrors @app.url_defaults - runs inside url_for / url_path_for for endpoints belonging to this blueprint. Use values.setdefault(...) for caller-wins semantics.

register_blueprint

register_blueprint(child: Blueprint, url_prefix: str | None = None) -> None

Mount another blueprint as a sub-blueprint of this one.

Routes from child register under self.url_prefix + (url_prefix or child.url_prefix) + path; endpoint names stored on this blueprint become <child.name>.<handler> and pick up the <self.name>. prefix once this blueprint is itself registered with an app, yielding a final <self.name>.<child.name>.<handler> lookup name so the dispatcher's prefix-gate finds them under either name.

Hooks and error handlers from child are merged into this blueprint's lists (not the app's - the app gets them when this blueprint is registered).

URLRule

A single registered URL rule view object.

Iterable over its fields as (rule, methods, endpoint) so callers that just want tuple-unpack semantics work; the same three are available as attributes for introspection. Slotted, so there are no others - read anything further off the route table itself.

URLMap

Veloce's read-only Map-style route-table wrapper.

Iterating yields URLRule objects in registration order (grouped by (path, name) so each unique route is one rule even when several HTTP methods share it). len() counts unique rules. Lookup by endpoint name returns the list of matching rules.

View

Base class-based view - one dispatch_request per class.

Subclasses override dispatch_request. Class attributes:

  • methods - the HTTP verbs this view answers (advisory; used by the router / OpenAPI introspection).
  • decorators - decorators applied to the generated view function, innermost-first (the last entry wraps outermost).
  • init_every_request - when True (default) a fresh instance is built for each request; when False one instance is reused.

as_view classmethod

as_view(name: str, *class_args: Any, **class_kwargs: Any) -> Callable

Build a view function bound to this class.

Honours init_every_request (fresh instance per request vs a single shared one) and applies decorators. The returned callable carries view_class, methods, and __name__ = name for router introspection and url_for naming.

dispatch_request async

dispatch_request(*args: Any, **kwargs: Any) -> Any

Handle the request - subclasses must override.

MethodView

Bases: View

Class-based view dispatching one async method per HTTP verb.

Subclasses define get / post / ... as async def. methods is inferred from the defined verbs unless set explicitly.

as_view classmethod

as_view(name: str, *class_args: Any, **class_kwargs: Any) -> Callable

Build a view function bound to this class.

Honours init_every_request (fresh instance per request vs a single shared one) and applies decorators. The returned callable carries view_class, methods, and __name__ = name for router introspection and url_for naming.

dispatch_request async

dispatch_request(*args: Any, **kwargs: Any) -> Any

Pick the matching method by request verb and forward arguments.

The first positional argument is expected to be the Request; the rest are path parameters. If the class doesn't implement the verb, raises MethodNotAllowed with Allow: set.