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("Type used to filter and serialize the handler's return value and the OpenAPI response schema. Defaults to the handler's return annotation when it names a model; pass `None` to declare no response contract.")] = _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("Resource URI for the route's MCP resource: a static URI, or a URI template (`users://{user_id}`) binding its path parameters.")] = None, mcp_resource_mime_type: Annotated[str | None, Doc("Media type advertised for the route's MCP resource. Declared rather than inferred, so the listing never disagrees with what a read returns.")] = None, mcp_meta: Annotated[dict[str, Any] | None, Doc("`_meta` published on this route's MCP tool or resource, for metadata an extension defines rather than the protocol itself.")] = 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("Allow this route's MCP tool to run as a background task (task-augmented `tools/call`, polled via `tasks/get` / `tasks/result`).")] = False, exclude_middleware: Annotated[Sequence[str] | None, Doc('Names of middleware this route opts out of.')] = None, stream: Annotated[bool, Doc('Opt into request-body streaming: the body is not buffered before the handler, so the handler may consume `request.stream()` incrementally. The synchronous body accessors are unavailable on a streaming route until the body is drained.')] = 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 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("Type used to filter and serialize the handler's return value and the OpenAPI response schema. Defaults to the handler's return annotation when it names a model; pass `None` to declare no response contract.")] = _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("Resource URI for the route's MCP resource: a static URI, or a URI template (`users://{user_id}`) binding its path parameters.")] = None, mcp_resource_mime_type: Annotated[str | None, Doc("Media type advertised for the route's MCP resource.")] = None, mcp_meta: Annotated[dict[str, Any] | None, Doc("`_meta` published on this route's MCP tool or resource.")] = 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("Allow this route's MCP tool to run as a background task (task-augmented `tools/call`, polled via `tasks/get` / `tasks/result`).")] = False, exclude_middleware: Annotated[Sequence[str] | None, Doc('Names of middleware this route opts out of.')] = None, stream: Annotated[bool, Doc('Opt into request-body streaming: the body is not buffered before the handler, so the handler may consume `request.stream()` incrementally.')] = False) -> Callable
Generic route decorator.
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.
query
¶
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
Declarative WebSocket route - wrap 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
¶
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
¶
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. Usesapp.config["SERVER_NAME"]when set, otherwise falls back tolocalhost. Caller should override_scheme/_hostfor 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.
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("Type used to filter and serialize the handler's return value and the OpenAPI response schema. Defaults to the handler's return annotation when it names a model; pass `None` to declare no response contract.")] = _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("Resource URI for the route's MCP resource: a static URI, or a URI template (`users://{user_id}`) binding its path parameters.")] = None, mcp_resource_mime_type: Annotated[str | None, Doc("Media type advertised for the route's MCP resource. Declared rather than inferred, so the listing never disagrees with what a read returns.")] = None, mcp_meta: Annotated[dict[str, Any] | None, Doc("`_meta` published on this route's MCP tool or resource, for metadata an extension defines rather than the protocol itself.")] = 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("Allow this route's MCP tool to run as a background task (task-augmented `tools/call`, polled via `tasks/get` / `tasks/result`).")] = False, exclude_middleware: Annotated[Sequence[str] | None, Doc('Names of middleware this route opts out of.')] = None, stream: Annotated[bool, Doc('Opt into request-body streaming: the body is not buffered before the handler, so the handler may consume `request.stream()` incrementally. The synchronous body accessors are unavailable on a streaming route until the body is drained.')] = 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 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("Type used to filter and serialize the handler's return value and the OpenAPI response schema. Defaults to the handler's return annotation when it names a model; pass `None` to declare no response contract.")] = _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("Resource URI for the route's MCP resource: a static URI, or a URI template (`users://{user_id}`) binding its path parameters.")] = None, mcp_resource_mime_type: Annotated[str | None, Doc("Media type advertised for the route's MCP resource.")] = None, mcp_meta: Annotated[dict[str, Any] | None, Doc("`_meta` published on this route's MCP tool or resource.")] = 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("Allow this route's MCP tool to run as a background task (task-augmented `tools/call`, polled via `tasks/get` / `tasks/result`).")] = False, exclude_middleware: Annotated[Sequence[str] | None, Doc('Names of middleware this route opts out of.')] = None, stream: Annotated[bool, Doc('Opt into request-body streaming: the body is not buffered before the handler, so the handler may consume `request.stream()` incrementally.')] = False) -> Callable
Generic route decorator.
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.
query
¶
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
Declarative WebSocket route - wrap 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
¶
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
¶
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. Usesapp.config["SERVER_NAME"]when set, otherwise falls back tolocalhost. Caller should override_scheme/_hostfor 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.
include_router
¶
include_router(router: Router, prefix: str = '') -> None
Include another router (a sub-router with its own prefix, tags, and hooks).
before_request
¶
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
¶
Register a function to run after each blueprint request.
teardown_request
¶
Run after blueprint-routed request teardown, with optional exc.
errorhandler
¶
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
¶
Register a fn(endpoint, values) URL preprocessor on this blueprint.
Mirrors @app.url_value_preprocessor (R20) - 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
¶
Register a fn(endpoint, values) URL-defaults injector for url_for.
Mirrors @app.url_defaults (R21) - 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; full attribute access
gives rule, methods, endpoint, defaults, host, etc. for
introspection.
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
¶
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
¶
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
¶
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
¶
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.