Skip to content

API Reference

This page is generated from the docstrings of the public veloce package — every name exported from the top-level namespace.

Veloce — Ultra-fast async Python web framework.

Veloce is a high-performance asynchronous web framework built on raw asyncio, httptools, and orjson. It pairs a small, well-typed API with predictable performance under load.

Basic usage::

from veloce import Veloce, Request

app = Veloce()

@app.get("/")
async def index(request: Request):
    return {"message": "Hello, World!"}

app.run()

Veloce

Bases: Router

Ultra-fast async web framework.

Usage

app = Veloce()

@app.get("/") async def index(request: Request): return {"message": "Hello, World!"}

app.run()

url_map property

url_map: _URLMap

Read-only mapping of registered URL rules.

Iterating it yields URLRule objects (rule, methods, endpoint). Subscript by endpoint name (app.url_map["users.detail"]) returns a list of rules registered under that endpoint. Length is the total registered route count.

This is the introspection-friendly view of Veloce.routes; callers who just want the dict-list keep using app.routes.

routes property

routes: list[dict[str, Any]]

List all registered routes.

json property writable

json: Any

Active JSONProvider instance.

Lazily instantiated from app.json_provider_class so swapping encoders is just: app.json_provider_class = MyJSONProvider. Setting app.json = instance replaces it explicitly.

package_root property

package_root: str

Filesystem path of the directory containing import_name's module.

Veloce exposes this as app.root_path; veloce already uses Veloce.root_path for the ASGI mount prefix, so we surface the package-directory variant under a non-conflicting name. Useful for resolving template / static directories relative to the app's source file.

jinja_env property

jinja_env: Any

The app's shared Jinja2 Environment.

Available once a template_folder has been configured (either via the constructor or by binding Jinja2Templates). Mutate it directly to register filters/globals or tweak settings: app.jinja_env.filters["money"] = fmt. Raises RuntimeError when no templating is configured.

jinja_loader property

jinja_loader: Any

The app's Jinja template loader.

The FileSystemLoader (or whatever loader the bound Jinja2Templates env uses). None when no templating is configured — Veloce returns None for an app with no template folder rather than raising.

instance_path property

instance_path: str

Writable instance folder beside the package.

Veloce resolves <package_root>/instance as a per-deployment writable directory for config, SQLite files, uploads, etc. An explicit instance_path= constructor argument overrides this computed default. The directory is not auto-created — the caller decides whether to mkdir it.

signal_namespace property

signal_namespace: Any

Accessor that returns the veloce.signals module.

Veloce ships its signals as module-level singletons, so this attribute returns the module — app.signal_namespace.request_started is the same Signal instance as veloce.signals.request_started.

aborter property writable

aborter: Any

Callable that raises typed HTTPExceptions by status code.

app.aborter(404) is equivalent to the module-level abort(404) helper. It is a distinct attribute so applications can subclass Aborter to add custom code-to-exception mappings; veloce returns a fresh Aborter instance per access so users can mutate _mapping per-app without affecting others.

got_first_request property

got_first_request: bool

True after the first request has been fully handled.

compatibility — read-only. Useful when conditional setup depends on whether the app has bootstrapped yet, e.g. a before_first_request hook firing exactly once is reflected here as True.

cli property

cli: Any

Click Group for app-defined custom CLI commands.

Accessing app.cli lazily constructs a click.Group once. Custom commands attach via the standard Click decorator:

@app.cli.command("init-db")
def init_db():
    ...

The veloce console script automatically discovers and mounts the group as a custom subcommand when launched with an app reference. click is required at access time but not at import time — the ImportError is deferred and produces a useful message instead of a hard-import crash on environments that don't need the CLI.

view_functions property

view_functions: dict[str, Callable]

A {endpoint_name: handler} view of registered routes.

Endpoint names follow a simple rule — the route's name= kwarg, or the handler's __name__ when no name is set; blueprint routes are prefixed with <bpname>.. Returned dict is a fresh snapshot — mutation doesn't poison framework state.

error_handler_spec property

error_handler_spec: dict[Any, dict[Any, Callable]]

Inspection view of registered error handlers.

Returns a {blueprint_name_or_None: {key: handler}} mapping. veloce keeps a flat registry (no per-blueprint sub-tables — blueprint handlers are merged into the app's dicts at register_blueprint time), so this view always carries a single None key whose value contains every registered handler keyed by integer status code or exception class.

before_request_funcs property

before_request_funcs: dict[Any, list[Callable]]

View of registered before_request hooks.

Returns {blueprint_name_or_None: [hook, ...]}. App-level hooks live under the None key; blueprint hooks under the blueprint's name. The dispatcher walks the None bucket plus the bucket whose name matches the matched route's endpoint prefix.

blueprints property

blueprints: dict[str, Any]

snapshot mapping of bp.name -> Blueprint.

Returns a fresh copy, so caller mutations don't affect the framework. Re-registering the same name overwrites the previous entry.

url_value_preprocessors property

url_value_preprocessors: dict[Any, list[Callable]]

View of registered URL-value preprocessors.

Returns {blueprint_name_or_None: [fn, ...]}. Veloce flattens blueprint preprocessors into the app list at registration time, so the dict carries a single None key.

url_default_functions property

url_default_functions: dict[Any, list[Callable]]

View of registered URL-default callbacks.

dependency_overrides property writable

dependency_overrides: dict[Callable, Callable]

Mutable map of dependency callables to test replacements.

Populate it to swap a real dependency for a fake one in tests::

app.dependency_overrides[get_db] = get_fake_db

The resolver consults this map on every request, so changes take effect immediately. Assigning a fresh dict (or calling .clear()) removes all overrides.

add_middleware

add_middleware(middleware: Any, **options: Any) -> None

Add middleware to the pipeline.

Call forms:

  • add_middleware(VeloceMiddlewareClass, **options) — a class subclassing Middleware is instantiated with **options and appended to the request/response pipeline.
  • add_middleware(instance) — append an already-built Middleware instance directly.
  • add_middleware(ASGIMiddlewareClass, **options) — a class that is not a Middleware subclass is treated as a standard ASGI middleware: it wraps the whole application and is instantiated as ASGIMiddlewareClass(app, **options) when the ASGI stack is assembled. This is what lets third-party ASGI middleware (observability, tracing, profiling, ...) plug in. Middleware added first is the outermost wrapper.

add_instrumentation

add_instrumentation(hook: Callable) -> Callable

Register an observability instrumentation hook.

hook is called once per finished HTTP request with a RequestMetrics record — the request method, the concrete path, the matched route template (a low-cardinality metric label), the status code, and the wall-clock duration in milliseconds. It may be a plain function or a coroutine function. A hook that raises is logged and skipped, so instrumentation never breaks a response.

Returns hook unchanged, so it also works as a decorator:

@app.add_instrumentation
def export(metrics):
    statsd.timing(metrics.route or "unmatched", metrics.duration_ms)

With no hook registered the request path carries no instrumentation cost — not even a clock read.

use_secure_defaults

use_secure_defaults() -> None

Apply a security-hardened configuration baseline.

  • Marks the session cookie Secure, HttpOnly, and (unless already configured) SameSite=Lax.
  • Registers SecurityHeadersMiddlewarenosniff, frame-deny, a referrer policy, and a one-year HSTS max-age — unless one is already present.

Call once after construction, before serving. Production-oriented: the Secure cookie flag means cookies are not sent over plain HTTP, so do not call this for local HTTP development.

security_audit

security_audit() -> list[str]

Return human-readable warnings about the current security posture.

An empty list means nothing was flagged. Drives the veloce check CLI command and is also callable directly from a pre-deploy script or a test.

send_static_file

send_static_file(filename: str) -> Any

Serve a file from app.static_folder.

app.static_folder defaults to "static" (relative to app.package_root). Use app.static_url_path to control the URL prefix when mounting via app.static(...). Returns a FileResponse; traversal-safe via safe_join.

test_cli_runner

test_cli_runner(**kwargs: Any) -> Any

Return a Click CliRunner bound for testing app.cli.

Veloce exposes this for unit-testing @app.cli.command(...) handlers without manual Click import. Kwargs flow through to click.testing.CliRunner.

dispatch_request

dispatch_request(request: Request) -> Any

an alias for _dispatch_request.

full_dispatch_request

full_dispatch_request(request: Request) -> Any

an alias for _dispatch_request (which already runs the full before/after-request hook chain inline).

preprocess_request async

preprocess_request(request: Request) -> Any

Run all before_request hooks for request.

Walks the registered hooks in order; if any hook returns a non-None value it short-circuits the chain and that value is returned (the contract — a non-None return becomes the response). Both sync and async hooks are supported. App-level hooks fire first, then the matched-blueprint bucket — the same shape _dispatch_request uses.

process_response async

process_response(request: Request, response: Any) -> Any

Run all after_request hooks for (request, response).

Hooks fire in reverse registration order; each hook may return a replacement response (the contract: a None return keeps the existing response). App-level hooks reverse-iterate first, then the matched-blueprint bucket — mirrors _dispatch_request's ordering.

ensure_sync staticmethod

ensure_sync(func: Callable) -> Callable

Wrap func so it is callable from synchronous code.

  • If func is a regular function, returns it unchanged.
  • If func is a coroutine function, returns a sync wrapper that runs the coroutine to completion on a dedicated event loop and returns the result.

Use to bridge async handlers / hooks into sync code (CLI commands, background workers, test scaffolding).

async_to_sync staticmethod

async_to_sync(func: Callable) -> Callable

Force-wrap func (sync or async) into a synchronous callable.

Unlike ensure_sync this always returns a sync wrapper — useful when the caller needs a uniform (*a, **kw) -> result shape regardless of func's coroutinicity.

make_response

make_response(value: Any) -> Response

Coerce a handler-return value into a Response.

Accepts (with this coercion table): - Response → returned as-is - str / bytes → wrapped as a text/HTML response - dict / list → wrapped as a JSON response via jsonify - tuple of (body,), (body, status), (body, status, headers), or (body, headers) → unpacked and re-coerced

test_client

test_client(**kwargs: Any) -> Any

Return an in-memory TestClient for this app.

app.test_client() is the factory API; the kwargs (e.g. follow_redirects=True, base_url=...) are forwarded to TestClient.__init__. Equivalent to TestClient(app, **kwargs) for callers that prefer the method form.

async_test_client

async_test_client(**kwargs: Any) -> Any

Return an AsyncTestClient for this app.

The async counterpart of test_client() — used as async with app.async_test_client() as client: inside an async test, so requests are awaited on the test's own running loop rather than driven through a private loop. Kwargs are forwarded to AsyncTestClient.__init__.

app_context

app_context() -> _AppContext

Bind current_app and reset g for use outside a request.

Use as with app.app_context(): .... CLI commands, background jobs, and tests need this when they want to read app.config or write into g without going through handle_request. Nestable: the previous binding (if any) is restored on exit.

test_request_context

test_request_context(path: str = '/', method: str = 'GET', headers: dict[str, str] | None = None, query_string: str = '', body: bytes = b'') -> _TestRequestContext

Synthesise a fake request for outside-request testing.

Inside with app.test_request_context(): ..., current_app, g, and the request-scoped contextvars resolve as if Veloce had just received that request — without spinning up the full dispatch pipeline. Strict subset of what handle_request does: no middleware, no DI, no handler.

add_http_middleware

add_http_middleware(middleware: Any) -> Any

Register a BaseHTTPMiddleware-style middleware on the (request, call_next) -> response chain. Accepts an instance, a bare callable, or a class (which is instantiated with no args). Returns the registered object so it can be used as a decorator.

middleware

middleware(middleware_class_or_type: type | str, **kwargs) -> Any

Add middleware — supports both a class form and a decorator form.

Class form: app.middleware(CORSMiddleware, allow_origins=["*"]) Decorator form: @app.middleware("http") async def add_header(request, call_next): response = await call_next(request) response.headers["X-Custom"] = "value" return response

register_error_handler

register_error_handler(code_or_exception: int | type, func: Callable) -> None

Register an error handler without a decorator.

exception_handler

exception_handler(exc_class_or_status: type | int) -> Callable

Register a custom exception handler by exception type or status code.

add_exception_handler

add_exception_handler(exc_class_or_status: type | int, handler: Callable) -> None

Imperative exception-handler registration — ASGI shape.

The non-decorator form of @app.exception_handler(...). Accepts an exception class (matched by MRO at dispatch time) or an int HTTP status code.

log_exception

log_exception(exc: BaseException) -> None

Log an exception with traceback.

Routes the exception through the app logger at ERROR level. Used internally before falling back to a 500 response; exposed publicly so error-handler code can re-log via the same path.

handle_http_exception async

handle_http_exception(exc: HTTPException) -> Response

Build the response for an HTTPException.

Walks registered status-code + class handlers first (matching abort() semantics), falling back to JSON {"detail": exc.detail} with exc.headers applied. Useful for code paths outside the normal request cycle (e.g. background tasks) that want framework-consistent error shapes.

make_default_options_response

make_default_options_response(path: str) -> Response

Build the auto-OPTIONS response for path.

Returns a 200 response with an empty body and an Allow header listing every method registered for path, augmented with HEAD (whenever GET is supported) and OPTIONS itself per RFC 9110 §9.3.7. Callers that register an explicit OPTIONS handler can use this to compose the default Allow set.

trap_http_exception

trap_http_exception(exc: BaseException) -> bool

Decide whether an HTTPException should propagate.

Returns True iff the exception should be re-raised (skipping the configured errorhandler) for a debugger to see. Honours:

  • TRAP_HTTP_EXCEPTIONS = True — trap every HTTPException.
  • TRAP_BAD_REQUEST_ERRORS = True (default in debug mode) — trap only BadRequest/Unauthorized/Forbidden/NotFound style 4xx errors so unexpected 404s/400s surface during development. Non-HTTP exceptions are never trapped here.

handle_user_exception async

handle_user_exception(exc: BaseException) -> Response

Dispatch an arbitrary exception.

HTTPExceptionhandle_http_exception. Otherwise walks registered class handlers (MRO); on no match, logs via log_exception and returns 500.

endpoint

endpoint(name: str) -> Callable

Decorator attaching a function as the view for name on an already-registered route.

Useful when separating route declaration (via app.add_url_rule(rule, endpoint="x")) from view registration. Replaces the existing route's handler in place.

iter_blueprints

iter_blueprints() -> Any

iterate over every registered Blueprint.

Returns the blueprints in registration order (Python 3.7+ dict insertion order). Yields the Blueprint objects, not their names.

before_request

before_request(func: Callable) -> Callable

Register a function to run before each request.

shell_context_processor

shell_context_processor(func: Callable) -> Callable

Register a function returning a dict to merge into veloce shell.

each processor is called with no args; its dict becomes part of the namespace the interactive shell starts with. Useful for surfacing models / db sessions / common helpers so User.query.first() works without a manual from myapp.models import User every time.

make_shell_context

make_shell_context() -> dict[str, Any]

Build the dict the CLI's shell command drops into.

Always includes app (this Veloce instance) and g. Each registered shell-context-processor's return dict overlays on top, in registration order — later processors win on conflicts.

before_first_request

before_first_request(func: Callable) -> Callable

Register a function to run exactly once on the first request.

A legacy hook style — lifespan startup handlers are preferred, but first-request hooks are still a common pattern, so both are supported. Hooks fire serially in registration order; single-fire is guarded with an asyncio.Lock so concurrent first requests don't double-run the callbacks.

after_request

after_request(func: Callable) -> Callable

Register a function to run after each request.

teardown_request

teardown_request(func: Callable) -> Callable

Register a function to run after request teardown. Called with an optional exception argument, even if an exception occurred.

teardown_appcontext

teardown_appcontext(func: Callable) -> Callable

Register a function to run on app-context teardown.

context_processor

context_processor(func: Callable) -> Callable

Register a template context processor. The function should return a dict that merges into the template context.

template_filter

template_filter(name: str | None = None) -> Callable

Register a function as a Jinja filter.

Usage

@app.template_filter("upper") def upper(s): return s.upper()

The filter becomes available in every Jinja2Templates render that runs inside this app's request scope. name defaults to the function's own __name__.

template_global

template_global(name: str | None = None) -> Callable

Register a callable as a Jinja global — accessible from any template by name. Same shape as template_filter.

add_template_global

add_template_global(func: Callable, name: str | None = None) -> None

Imperative equivalent of @template_global.

template_test

template_test(name: str | None = None) -> Callable

Register a Jinja test — used in {% if x is name %} constructs.

add_template_filter

add_template_filter(func: Callable, name: str | None = None) -> None

Imperative equivalent of @template_filter.

add_template_test

add_template_test(func: Callable, name: str | None = None) -> None

Imperative equivalent of @template_test.

update_template_context

update_template_context(context: dict[str, Any]) -> dict[str, Any]

Merge registered context-processor output into context.

Runs every @app.context_processor callback and folds the returned dicts into context in place, without overriding keys the caller already set (the documented semantics — explicit context wins). Returns the same dict for chaining.

url_value_preprocessor

url_value_preprocessor(func: Callable) -> Callable

Register a function fn(endpoint, values) that can mutate the matched path params before the handler runs.

Usage

@app.url_value_preprocessor def pull_lang(endpoint, values): from veloce import g g.lang = values.pop("lang", "en")

endpoint is the route name; values is the path_params dict (mutating it in place is the supported way to remove / rewrite values before the handler sees them).

url_for

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

Veloce.url_for runs @app.url_defaults callbacks before delegating to Router.url_for, so injected defaults appear in the rendered URL.

On build failure (unknown endpoint or missing path parameter), each registered app.url_build_error_handlers callback is invoked with (error, endpoint, values) in order; the first non-None return is used. If none recovers, a BuildError is raised.

url_defaults

url_defaults(func: Callable) -> Callable

Register a function fn(endpoint, values) that injects default kwargs into every url_for / url_path_for call.

Usage

@app.url_defaults def add_lang(endpoint, values): from veloce import g values.setdefault("lang", g.get("lang", "en"))

Runs in registration order; mutate values in place.

include_router

include_router(router: Any, prefix: str = '', url_prefix: str | None = None) -> None

Mount a sub-router include_router.

Accepts either a Blueprint (delegates to register_blueprint, honouring its hooks / error handlers / url processors) or a plain Router (delegates to Router.include_router). The prefix and url_prefix are interchangeable; both spellings spells it prefix, Veloce spells it url_prefix.

register_blueprint

register_blueprint(blueprint: Any, url_prefix: str | None = None) -> None

Mount a Blueprint's routes + hooks onto this app.

  • Re-registers each route under (url_prefix or bp.url_prefix) + path so the same blueprint can be mounted twice (e.g. v1/v2 versions).
  • Splices the blueprint's before_request / after_request / teardown_request hooks into the app's own lists. Blueprint hooks fire only for blueprint-routed requests (gated via request.endpoint starting with "<bpname>."); we tag the blueprint's hooks so the dispatcher can filter.
  • Splices blueprint-level error handlers into the app's tables; app-level handlers take precedence on conflicts because they're already registered.

Mountable multiple times on different apps with different prefixes — the blueprint itself stays unmodified.

add_url_rule

add_url_rule(rule: str, endpoint: str | None = None, view_func: Callable | None = None, methods: list[str] | None = None, **kwargs: Any) -> None

Add a URL rule programmatically.

view_func=None registers an endpoint-only stub: the route exists for url_for resolution but has no handler yet. Attach one later with @app.endpoint(endpoint). Calling such a route before a handler is attached raises a clear RuntimeError. Requires endpoint to be set in the stub case.

mount

mount(prefix: str, app: Any) -> None

Mount a sub-application at a path prefix.

A veloce sub-app is dispatched through the parent's request pipeline. Any other ASGI application — an ASGI micro-app, an instrumentation shim — is dispatched at the ASGI layer instead: the matched prefix is stripped from the scope's path and moved onto root_path, so the mounted app sees a normal root-relative request.

Scope: a mounted ASGI app receives http and websocket scopes only. The parent app owns the lifespan cycle and does not fan it out, so a mounted app must not depend on ASGI lifespan events for its setup. A mounted ASGI app owns its entire prefix subtree — a native route registered under the same prefix is unreachable.

Prefixes must not overlap: registering a prefix equal to, nested under, or containing an existing mount raises ValueError, since overlapping mounts would shadow each other in a confusing, order-dependent way.

on_event

on_event(event: str) -> Callable

Register startup/shutdown event handlers.

add_event_handler

add_event_handler(event: str, func: Callable) -> None

Imperative event-handler registration — ASGI shape.

app.add_event_handler("startup", fn) is the non-decorator form of @app.on_event("startup"). event must be "startup" or "shutdown".

before_serving

before_serving(func: Callable) -> Callable

Register a coroutine to run once at app startup.

after_serving

after_serving(func: Callable) -> Callable

Register a coroutine to run once at app shutdown.

mount_static

mount_static(prefix: str = '/static', directory: str = 'static', html: bool = False) -> None

Mount a static file directory.

handle_request async

handle_request(request: Request) -> Response

Main request handler — runs middleware chain + route dispatch.

openapi

openapi() -> dict[str, Any]

Return the generated OpenAPI schema dict.

Computes the schema on first call, caches the result in app.openapi_schema. Subsequent calls return the cached dict; users can mutate the result in place (e.g. to inject custom info.x-logo or tags orderings) and the swagger UI / json endpoints will serve the mutated copy.

To bypass the auto-build entirely, assign a custom dict to app.openapi_schema before any request lands.

run

run(host: str = '0.0.0.0', port: int = 8000, workers: int = 1, access_log: bool = True, ssl_context: SSLContext | None = None) -> None

Start the built-in development server.

Veloce's from-scratch HTTP server is intended for local development only. For production, run the app under a hardened ASGI server — uvicorn your_module:app — which veloce is fully compatible with through its ASGI __call__ interface. run() logs a reminder of this on startup.

ssl_context — an ssl.SSLContext — turns on HTTPS for local testing; it is handed straight to loop.create_server(ssl=...). Left None (the default) the serving path is byte-for-byte the same as plain HTTP. Production should still terminate TLS at uvicorn or a reverse proxy.

lifespan_context

lifespan_context() -> _LifespanManager

Return an async context manager driving the lifespan cycle.

async with app.lifespan_context(): ... runs the full startup sequence (lifespan CM enter + on_startup handlers) on entry and the shutdown sequence on exit — independent of any request. Useful for tests and for embedding the app where you want startup/shutdown without an ASGI server in the loop.

BackgroundTask

A single background task.

BackgroundTasks

Collection of background tasks to run after response.

Blueprint

Bases: Router

Deferred-registration route collection.

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 (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

url_defaults(func: Callable) -> Callable

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 become <self.name>.<child.name>.<handler> 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).

StaticFiles

Serve static files from a directory — all file I/O runs in executor.

handle async

handle(request: Request) -> Response | None

Handle a static file request — file I/O offloaded to thread pool.

Jinja2Templates

Jinja2 template engine integration.

Usage

templates = Jinja2Templates(directory="templates")

@app.get("/page") async def page(request: Request): return templates.TemplateResponse("page.html", {"request": request, "name": "World"})

Any callables registered via @app.context_processor run before each render; their returned dicts are merged into the template context (caller's explicit context wins on collisions).

TemplateResponse

TemplateResponse(name: str, context: dict[str, Any], status_code: int = 200, headers: dict[str, str] | None = None) -> HTMLResponse

Render a template and return as HTMLResponse.

render

render(name: str, context: dict[str, Any] | None = None) -> str

Render a named template to a string (no Response wrapping).

Mirrors TemplateResponse but stops at the string stage so the render_template(name, **ctx) helper can plug in without building an HTMLResponse around the result.

render_string

render_string(source: str, context: dict[str, Any]) -> str

Render a template from string.

render_async async

render_async(name: str, context: dict[str, Any] | None = None) -> str

Asynchronously render a named template — Jinja enable_async.

Uses a separate async-enabled Environment (built lazily) so {% include %}d templates with async I/O resolve without blocking the loop. Filters/globals registered on app are synced onto the async env too.

get_template

get_template(name: str)

Get a raw Jinja2 template object.

Depends

Dependency marker — use in function signature defaults.

dependency may be omitted (Depends()); the resolver then infers it from the parameter's type annotation — the shorthand for x: SomeClass = Depends().

Security

Bases: Depends

Dependency marker with OAuth2 scopes for OpenAPI emission.

SecurityScopes

Aggregated OAuth 2.0 scopes for the current Security() chain.

A handler / sub-dependency that declares a parameter of this type receives the union of all Security(..., scopes=[...]) calls between the route entry and this point in the dependency graph. Typical use: an authorising dependency checks security_scopes.scopes against the scopes the bearer token actually carries and builds a WWW-Authenticate: Bearer scope="<...>" header when denying.

Per RFC 6749 §3.3 the scope-string serialisation is space-separated.

BuildError

Bases: LookupError

url_for could not build a URL for the given endpoint.

Carries the endpoint name and the values that were being substituted so registered app.url_build_error_handlers callbacks can recover (e.g. fall back to a different endpoint, or fetch from an external routing table) by inspecting the failure and returning a URL string.

HTTPException

Bases: Exception

HTTP error with status code and detail.

Either subclass with a fixed code (and optional description), or instantiate HTTPException(status_code, detail, headers) directly.

RequestValidationError

Bases: ValidationError

Framework-level request validation failure (422).

Raised by the dependency resolver when path / query / header / cookie / body / form / file parameters fail validation. Distinct from a user-level ValidationError so handlers can pick one or the other:

@app.exception_handler(RequestValidationError)
async def on_req_invalid(request, exc):
    return JSONResponse({"errors": exc.errors}, status_code=422)

Subclasses ValidationError so existing except ValidationError handlers continue to catch it via the MRO walk.

ValidationError

Bases: UnprocessableEntity

Request validation error (422).

Subclasses UnprocessableEntity so handlers registered against either UnprocessableEntity or HTTPException catch it via the MRO walk Veloce performs in error dispatch.

WebSocketDisconnect

Bases: Exception

WebSocket connection closed.

WebSocketException

Bases: Exception

Raised inside a WebSocket handler to close the connection cleanly.

ASGI shape. The dispatch layer catches it and sends a close frame carrying code (RFC 6455 §7.4.1) and the optional reason — no traceback is propagated, since this is an application-driven close rather than an internal error.

WebSocketRequestValidationError

Bases: RequestValidationError

A WebSocket dependency failed parameter validation.

Raised when a Depends() resolved during a WebSocket handshake reports a RequestValidationError. The dispatch layer closes the connection with code 1008 (policy violation) rather than 1011 (internal error), since the failure is a client-side contract violation, not a server fault.

URL

Parsed URL with component access — lazily constructed.

AcceptHeader

Parsed Accept-* header with RFC 9110 §12.5 q-value semantics.

Construction is via AcceptHeader.parse(raw, mime=False). mime=True enables MIME-style wildcard matching (text/*, */*) used by Accept; defaults to plain string equality used by Accept-Language, Accept-Encoding, Accept-Charset.

values property

values: list[str]

All accepted values in the order the client sent them.

parse classmethod

parse(raw: str, mime: bool = False) -> AcceptHeader

Parse a comma-separated header into (value, q) tuples.

Q-values missing or unparseable default to 1.0 (RFC 9110 §12.4.2). Entries with q=0 are kept — best_match treats them as explicit rejections of that option.

quality

quality(value: str) -> float

Return the q-value the client assigned to value.

For MIME headers, matches */* and type/* wildcards. Returns 0 when the value is rejected or not mentioned (callers usually special-case this).

best_match

best_match(options: list[str], default: str | None = None) -> str | None

Return the option the client accepts with the highest q-value.

Ties go to the order in options (caller's preference). Returns default when no option has q>0. When the header is empty (no preference expressed), returns options[0] — RFC 9110 §12.5.1 treats a missing Accept as "accept anything".

Authorization

Parsed Authorization header.

Two common shapes are first-class: - Basic (RFC 7617): .type == "basic", .username + .password set. - Bearer (RFC 6750): .type == "bearer", .token set.

Other schemes (Digest per RFC 7616, Negotiate, custom) populate .params with the comma-separated key="value" parameters parsed from the credentials portion; .type is the scheme name lower-cased.

Construction is via Authorization.from_header(value) which returns None for empty / malformed inputs rather than raising.

from_header classmethod

from_header(header_value: str) -> Authorization | None

Parse an Authorization: header value. Returns None on miss.

FormData

Bases: MultiDict

Multi-value form-field collection (text fields + file uploads).

Backed by multidict.MultiDict. Repeated form fields (<input name="a"> submitted twice, or repeated multipart parts with the same name) preserve every value; single-value access form["a"] returns the first. getlist("a") returns the full list.

get_upload

get_upload(key: str) -> UploadFile | None

Return the first value if it is an UploadFile, else None.

Headers

Bases: CIMultiDict

Case-insensitive, multi-value header collection.

Backed by multidict.CIMultiDict. Existing single-value access via headers["X"] returns the first value (multidict semantics); use headers.getlist("X") to get all values. Construction from a plain dict, a list of tuples, or another multidict all work — the underlying constructor handles each shape.

getlist

getlist(key: str) -> list

Alias for getall. Empty list if absent.

to_wsgi_list

to_wsgi_list() -> list[tuple[str, str]]

Return headers as a list of (name, value) tuples.

Preserves insertion order and every duplicate. Useful for emitting to a WSGI/ASGI layer or for round-tripping.

copy

copy() -> Headers

Return a shallow copy — a fresh Headers with the same entries.

add

add(key: str, value: str, **params: str) -> None

Append a header, with optional key=value parameters.

headers.add("Content-Disposition", "attachment", filename="x.txt") emits attachment; filename="x.txt". Parameter values containing whitespace or punctuation are double-quoted. Underscores in parameter names map to hyphens.

RangeSpec

Parsed Range: header (RFC 9110 §14.2).

  • unit is the range unit, e.g. "bytes" (the only commonly-used one).
  • ranges is a list of (start, end) tuples, with None standing in for an open endpoint:
    • 0-499(0, 499)
    • 1000-(1000, None) (open at the right)
    • -500(None, 500) (suffix-range — last 500 bytes)

parse classmethod

parse(header_value: str) -> RangeSpec | None

Parse a Range: header. Returns None on a missing or unparseable value rather than raising.

UploadFile

Uploaded file with an async read/write interface.

save

save(destination: str | BinaryIO, buffer_size: int = 16384) -> None

Stream this upload into destination.

  • destination is either a filesystem path (str) or an already-open binary file object. With a path, the file is opened in "wb" mode and closed afterwards; with a file object, the caller stays responsible for closing it.
  • buffer_size controls the chunk size used while streaming — keeps memory bounded for large uploads without loading them fully into RAM.

The upload's read cursor is reset to 0 before reading and restored to its prior position afterwards so the upload remains available for re-inspection.

Request

Incoming HTTP request with lazy attribute parsing.

All expensive operations (JSON parsing, cookie parsing, URL construction, form/multipart parsing) are deferred until accessed — zero overhead for properties you don't use.

query_params property

query_params: QueryParams

Parse query string lazily — only when accessed.

Repeated keys are preserved: params.getlist("tag") returns every value; params["tag"] returns the first.

args property

args: QueryParams

an alias for query_params — the parsed URL query string.

data property

data: bytes

Raw request body bytes — request.data shape.

The sync-property form of get_data(). Returns the body exactly as received, with no decoding or form parsing.

view_args property

view_args: dict[str, Any]

an alias for path_params — the matched route's path params.

Veloce names the dict of URL-captured values request.view_args; veloce calls it path_params. Both point at the same dict.

cookies property

cookies: Cookies

Parse cookies from the Cookie header — lazy, MultiDict-shaped.

Returns a Cookies (MultiDict). cookies["name"] gives the first value; cookies.getlist("name") gives every value when a name repeats (rare but valid per RFC 6265).

url property

url: Any

Full URL object — lazy construction.

base_url property

base_url: str

Base URL (scheme + host).

full_path property

full_path: str

Path + ? + query string. Always contains a ? even when the query string is empty.

url_root property

url_root: str

Root URL of the request: scheme://host/ (with trailing slash, no path or query string).

host_url property

host_url: str

Alias for url_root — Veloce exposes both names.

mimetype property

mimetype: str

Content-Type without parameters.

application/json; charset=utf-8application/json. Lower-cased and stripped — per RFC 9110 §8.3 the media type is case-insensitive.

mimetype_params property

mimetype_params: dict[str, str]

Parameters from Content-Type (e.g. {"charset": "utf-8"}).

Each parameter is key=value; quoted values have their surrounding double-quotes stripped. Keys are lower-cased; values preserve case.

client property

client: Address | None

The connecting peer as an Address(host, port).

request.client.host / request.client.port work, and tuple unpacking (host, port = request.client) works too. Returns None when the peer is unknown (e.g. synthetic requests). Honours ProxyFix — client.host reflects the trusted client IP.

is_xhr property

is_xhr: bool

Detect XMLHttpRequest-style AJAX calls.

The convention is X-Requested-With: XMLHttpRequest, set by jQuery, fetch wrappers, and similar libraries. It's a hint, not a guarantee (the client controls the header), but it's the traditional signal application code uses to switch between full HTML responses and partial / JSON ones.

scheme property

scheme: str

Request scheme — "http" or "https".

Sourced from the ASGI scope["scheme"] when present, then from the X-Forwarded-Proto header (only meaningful behind a trusted proxy), then default http.

max_content_length property

max_content_length: int | None

The body-size cap for this request.

Reads app.config["MAX_CONTENT_LENGTH"] from the bound app (the dispatcher enforces it, returning 413 on overflow). None — no limit — when unset or no app is bound.

origin property

origin: str | None

The Origin header — RFC 6454. None when absent.

Set by browsers on cross-origin requests (and all CORS preflights). CORS middleware matches the allow-list against it.

access_control_request_method property

access_control_request_method: str | None

CORS preflight Access-Control-Request-Method — RFC 6454.

On an OPTIONS preflight, names the method the real request will use. None outside a preflight.

access_control_request_headers property

access_control_request_headers: list[str]

CORS preflight Access-Control-Request-Headers — header list.

The headers the real request intends to send, lower-cased and whitespace-trimmed. Empty list when the header is absent.

accept_mimetypes property

accept_mimetypes: AcceptHeader

Parsed Accept header with MIME wildcard matching.

accept_languages property

accept_languages: AcceptHeader

Parsed Accept-Language header. q-value ordered.

accept_encodings property

accept_encodings: AcceptHeader

Parsed Accept-Encoding header (e.g. gzip, br).

accept_charsets property

accept_charsets: AcceptHeader

Parsed Accept-Charset header.

date property

date: Any

The request Date header as a tz-aware UTC datetime.

RFC 9110 §6.6.1 — the originator's timestamp for the message. Returns None when the header is missing or unparseable.

if_modified_since property

if_modified_since: float | None

Parse If-Modified-Since (RFC 9110 §13.1.3) to a Unix timestamp.

Accepts IMF-fixdate, obsolete RFC 850, and ANSI C asctime() forms. Returns None when the header is missing or unparseable — never raises, so callers can use it in a single branch.

range property

range: RangeSpec | None

Parse Range: header per RFC 9110 §14.2. Returns None when absent or unparseable.

if_match property

if_match: tuple[str, ...]

Parse If-Match (RFC 9110 §13.1.1) into a tuple of ETags.

Returns ("*",) for the wildcard, an empty tuple when the header is absent, otherwise a tuple of quoted ETags (quotes and any W/ weak prefix preserved verbatim).

If-Match is the write-side companion to If-None-Match: precondition that fails the request with 412 Precondition Failed when none of the listed ETags matches the resource's current ETag. Standard guard against the lost-update problem.

if_range property

if_range: tuple[str, float | None]

Parse If-Range: (RFC 9110 §13.1.5).

The header carries either an ETag or an HTTP-date — never both. Returns (etag, None) when the value is an ETag (quoted, possibly weak-prefixed) and ("", timestamp) when it parses as a date. Returns ("", None) when the header is absent or unparseable. Caller picks the relevant slot.

Used by GET with Range: to convert a partial-content request into a full 200 when the cached resource is stale.

if_unmodified_since property

if_unmodified_since: float | None

Parse If-Unmodified-Since (RFC 9110 §13.1.4) to a Unix timestamp.

Returns None when the header is missing or unparseable. Write-side companion to If-Modified-Since: precondition that fails with 412 when the resource has been modified since the given date.

if_none_match property

if_none_match: tuple[str, ...]

Parse If-None-Match (RFC 9110 §13.1.4) into a tuple of ETags.

Returns ("*",) when the header is the literal * (matches any existing representation), an empty tuple when the header is missing, or a tuple of one or more quoted ETags (the quotes are preserved so callers can compare them verbatim against an ETag header on the response).

auth property

auth: Authorization | None

Lazy-parse the Authorization: header into a typed object.

Returns None when the header is missing. Basic and Bearer schemes populate .username/.password and .token respectively; other schemes carry their key=value parameters in .params.

referrer property

referrer: str

Value of the Referer request header.

Spelling preserved from the original RFC misprint (RFC 7231 §5.5.2 documents Referer, not Referrer). The accessor uses the corrected spelling so callers don't have to remember.

root_path property

root_path: str

ASGI scope["root_path"] — the URL prefix the app is mounted under.

Comes from the ASGI server (e.g. uvicorn --root-path /api) or from app.mount("/sub", inner_app). Used so an app behind a prefix can generate correct external URLs without knowing the prefix at code-time.

Returns the empty string when the app is at root.

script_root property

script_root: str

an alias for root_path — also called script_root.

ProxyFix-style middleware may also set _state["proxy_fix_prefix"]; that wins over the ASGI scope because it represents the trusted outer-edge prefix when the ASGI server is behind a reverse proxy that strips the prefix.

subdomain property

subdomain: str

Leftmost host label minus app.config["SERVER_NAME"].

Returns the empty string when the request host equals SERVER_NAME exactly (apex), or when SERVER_NAME isn't configured and the host has no dots. With SERVER_NAME set, the returned value is the prefix that wouldn't match the configured apex; without it, the leftmost label.

is_multipart property

is_multipart: bool

True when the request body is multipart/*.

is_form property

is_form: bool

True when the body is application/x-www-form-urlencoded or multipart/form-data.

content_encoding property

content_encoding: str

Value of the Content-Encoding header.

Returns the lowercased encoding name ("gzip", "br", etc.) or the empty string when the header is missing.

content_language property

content_language: str

Value of the Content-Language header — RFC 9110 §8.5.

Returns the raw header value (a comma-separated list of language tags) or the empty string when the header is absent.

pragma property

pragma: str

Value of the legacy Pragma header — RFC 9111 §5.4.

Almost always no-cache from HTTP/1.0 clients. Returns the empty string when absent. Prefer cache_control for HTTP/1.1.

max_forwards property

max_forwards: int | None

The Max-Forwards header as an int — RFC 9110 §7.6.2.

Bounds how many proxies a TRACE/OPTIONS request may traverse. None when absent or non-numeric.

environ property

environ: dict

Alias for the ASGI scope dict.

third-party code paths reach for request.environ (WSGI); ASGI scope is the analogue. Returns the live dict so middleware can introspect (mutation goes through framework APIs, not this).

host property

host: str

Value of the Host request header.

Mirrors Request.url.netloc for the common case but pulls directly from the header to remain cheap (no full URL parse). Returns the empty string when the header is absent.

remote_addr property

remote_addr: str | None

an alias for client_host — the connecting client's IP.

Honours ProxyFix-style middleware: when the trusted hop has set _state["proxy_fix_client"], that value wins over the raw TCP peer (the ASGI/uvicorn client[0] may be the load balancer).

access_route property

access_route: list[str]

Forwarded-for chain.

Returns the comma-separated X-Forwarded-For values (client → proxy chain order), with the connecting peer (remote_addr) appended at the end. With no X-Forwarded-For header, returns [remote_addr] when the peer is known, else [].

RFC 7239 §5.2 defines the IP-order convention: leftmost is the originating client, rightmost is the closest proxy. Production code should consume the leftmost trusted entry, not blindly the leftmost value.

charset property

charset: str

Request body charset, decoded from Content-Type.

Defaults to utf-8 when no charset is declared (the modern default; the also moved off ISO-8859-1).

state property

state: State

Per-request scratch namespace — ASGI shape.

Supports attribute access (request.state.user = ...) and dict access (request.state["user"], request.state.get(...)).

session property

session: dict[str, Any]

Access to the session dict.

SessionMiddleware writes the parsed session into _state["session"] during process_request. This property surfaces it under the a convenience accessor. Raises RuntimeError when the middleware hasn't run — keeps "I forgot to add SessionMiddleware" from showing up as a confusing silent empty-dict.

url_rule property

url_rule: str | None

the matched route's template (e.g. /users/{id}).

Returns the raw path template the radix tree used for the match — i.e. path_params placeholders are unsubstituted. None for synthetic requests that never went through dispatch.

blueprint property

blueprint: str | None

the name of the blueprint that owns the matched route.

Veloce stores the endpoint as <bp>.<name> for blueprint routes. Returns the bit before the dot, or None if the endpoint is unset or is a top-level (no-dot) name.

blueprints property

blueprints: list[str]

every blueprint in the matched endpoint's parent chain.

For an endpoint a.b.c.view, returns ["a.b.c", "a.b", "a"] (innermost first). Empty list when the route is top-level or the endpoint is unset.

cache_control property

cache_control: Any

Parsed Cache-Control header.

Returns a CacheControl view: req.cache_control.no_cache (bool), req.cache_control.max_age (int or None), etc. Always returns a fresh parse to reflect any header mutation.

is_json property

is_json: bool

True for application/json or any application/*+json subtype.

Per RFC 6839 §3.1 the structured-suffix +json (e.g. application/vnd.api+json, application/problem+json) marks the body as JSON-encoded.

json async

json() -> Any

Parse the request body as JSON, async to match Starlette / FastAPI / Quart.

Veloce buffers the body at construction time, so no I/O actually happens inside the await — the coroutine resolves immediately with the cached parse. The async signature exists so the await request.json() idiom Starlette and FastAPI callers reach for first does not blow up at runtime.

For Flask muscle-memory call request.get_json() instead — that remains synchronous to match Flask's Request.get_json.

get_data

get_data(as_text: bool = False, cache: bool = True) -> bytes | str

Return the raw request body.

  • as_text=True decodes via the Content-Type charset (default UTF-8). Falls back to latin-1 when the declared charset is unrecognised — a defensive fallback, since latin-1 round-trips arbitrary bytes without raising.
  • cache=True is a no-op today (veloce already buffers the whole body on construction) but keeps the parameter so callers that pass cache=False for streaming compatibility don't break. Streaming-body support arrives separately.

Returns bytes (default) or str (with as_text=True).

get_json

get_json(force: bool = False, silent: bool = False, cache: bool = True) -> Any

Parse the request body as JSON.

  • force=True skips the is_json content-type check; useful when the client sends JSON without setting Content-Type (e.g. some XHR libraries). Default is to honour the content type and return None for non-JSON requests.
  • silent=True swallows orjson.JSONDecodeError and returns None. Default raises so caller code can distinguish malformed JSON from missing JSON.
  • cache=False forces a re-parse on every call. Default caches the parsed value (one parse per request); cache invalidation is the caller's job when cache=False.

Returns None for empty bodies regardless of force / silent.

on_json_loading_failed

on_json_loading_failed(error: Exception) -> Any

Hook invoked when get_json() fails to parse a non-silent body.

Override on a Request subclass to customise the failure behaviour (e.g. raise a BadRequest with a friendly message, or return a sentinel). The default re-raises the original decode error so malformed JSON surfaces loudly.

form async

form() -> Any

Parse form data including file uploads.

files async

files() -> Any

View of uploaded files only — a FormData subset.

Parses the form (via form()) and returns a FormData containing just the entries whose value is an UploadFile. Non-file form fields are excluded. Empty FormData for non-multipart requests.

url_for

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

Reverse-resolve a route URL — ASGI shape.

request.url_for("route_name", id=7) delegates to the bound app's url_for. Raises RuntimeError when the request has no app bound (synthetic requests built outside dispatch).

values async

values() -> Any

Merged query string + form body — request.values shape.

Returns a fresh MultiDict with query-string entries first, then form-body entries appended. Both source MultiDicts preserve repeated keys; merging preserves the order across both sources. Form parsing is async (multipart may need executor reads), so this is an awaitable rather than a property.

text async

text() -> str

Return body as text.

is_disconnected async

is_disconnected() -> bool

Whether the client has disconnected.

Veloce fully buffers the request body before dispatch, so by the time a handler runs the body is already received and the connection cannot be "disconnected mid-handler" in the ASGI sense. Always returns False; the method exists so handlers that poll await request.is_disconnected() keep working unchanged.

stream async

stream() -> Any

Async-iterate the request body in bounded chunks — ASGI shape.

The body is buffered before dispatch, so the chunks are sliced from that buffer rather than pulled from the socket; each yielded slice is capped at 64 KiB so a handler written against the streaming API (async for chunk in request.stream(): ...) can process a large body incrementally without materialising a second full copy of it.

FileResponse

Bases: Response

Serve a file from disk — uses async I/O via executor.

from_path async classmethod

from_path(path: str, filename: str | None = None, content_type: str | None = None, headers: dict[str, str] | None = None, content_disposition_type: str = 'attachment') -> FileResponse

Async factory — reads file in executor to avoid blocking event loop.

HTMLResponse

Bases: Response

HTML response.

JSONResponse

Bases: Response

JSON response using orjson for speed.

ORJSONResponse

Bases: JSONResponse

Explicit orjson-backed JSON response.

JSONResponse already uses orjson for encoding, so this class is a semantic alias — useful when route declarations want to communicate the encoder choice via response_class=ORJSONResponse.

PlainTextResponse

Bases: Response

Plain text response.

RedirectResponse

Bases: Response

HTTP redirect.

Response

Base HTTP response.

is_json property

is_json: bool

True when Content-Type is JSON.

Matches application/json and any application/*+json structured suffix (RFC 6839 §3.1).

mimetype property writable

mimetype: str

The bare media type — Content-Type without parameters.

text/html; charset=utf-8text/html. Lower-cased and stripped per RFC 9110 §8.3 (media types are case-insensitive).

status property writable

status: str

Full HTTP status line, e.g. "200 OK".

Assignable: accepts an int (200), a bare numeric string ("200"), or a full status line ("200 OK" / "404 Not Found"). The leading integer is parsed into status_code.

content_length property

content_length: int

Length of the response body in bytes.

Always derived from len(body). Streaming responses (which don't materialise the body) return 0 here; see is_streamed.

is_streamed property

is_streamed: bool

True when the response body is a streaming iterator.

charset property writable

charset: str

Response charset from Content-Type.

Falls back to "utf-8" when no charset parameter is present. Assignable: setting it rewrites the charset= parameter on the existing Content-Type (the bare media type is preserved).

mimetype_params property

mimetype_params: dict[str, str]

Parameters of the Content-Type header.

Everything after the bare media type, as a dict of lower-cased parameter names to their (unquoted) values. For text/html; charset=utf-8 this is {"charset": "utf-8"}. Returns an empty dict when no parameters are present.

last_modified property writable

last_modified: Any

Parsed Last-Modified header → UTC datetime or None.

Accepts the three RFC 9110 §5.6.7 HTTP-date forms. Returns None on missing/unparseable.

expires property writable

expires: Any

Parsed Expires header → UTC datetime or None (RFC 9111 §5.3).

cookies property

cookies: dict[str, str]

Parsed cookie jar from this response's Set-Cookie header(s).

Walks every Set-Cookie entry (Q44 separator \r\nSet-Cookie: respected) and returns {name: value}. Multiple cookies with the same name resolve to the last set — matches the wire behaviour where the client also keeps the most-recent value. Caller introspection only; mutation goes through set_cookie().

headerlist property

headerlist: list[tuple[str, str]]

Headers flattened to a (name, value) tuple list.

Each Set-Cookie (Q44 multi-cookie join) expands to its own tuple, so downstream wire-emit / inspection code gets the per-cookie view ASGI requires.

data property writable

data: bytes

Body bytes alias for Response.body.

Read returns the current body; writing through the setter replaces the body, invalidates any cached HTTP/1.1 encoded bytes (_encoded), and updates Content-Length on the headers if it was previously set.

vary property writable

vary: Any

The Vary header as a HeaderSet.

Returns a fresh HeaderSet parsed from the current header. Assign a HeaderSet, iterable of strings, or a comma-separated string to replace it. Mutating the returned object does not write back — call add_vary(...) or reassign for that.

allow property writable

allow: Any

The Allow header as a HeaderSet.

Lists the HTTP methods the resource supports (RFC 9110 §10.2.1). Assign a HeaderSet, iterable, or comma-separated string.

www_authenticate property writable

www_authenticate: str | None

The WWW-Authenticate challenge header — RFC 9110 §11.6.1.

Sent on 401 Unauthorized to tell the client which auth scheme(s) to use. None when unset.

content_encoding property writable

content_encoding: str | None

The Content-Encoding header — RFC 9110 §8.4. None when unset.

content_language property writable

content_language: str | None

The Content-Language header — RFC 9110 §8.5. None when unset.

accept_ranges property writable

accept_ranges: str | None

The Accept-Ranges header — RFC 9110 §14.3.

Typically bytes (range requests supported) or none (explicitly unsupported). None when the header is unset.

content_range property

content_range: str | None

The raw Content-Range header — RFC 9110 §14.4. None if unset.

date property writable

date: Any

The Date header as a tz-aware UTC datetime — RFC 9110 §6.6.1.

Returns None when unset or unparseable. Assign a datetime or POSIX timestamp to set it; assign None to remove it.

location property writable

location: str | None

The Location header — RFC 9110 §10.2.2. None when unset.

content_location property writable

content_location: str | None

The Content-Location header — RFC 9110 §8.7. None when unset.

retry_after property writable

retry_after: Any

The Retry-After header — RFC 9110 §10.2.3.

Returns an int (delay in seconds) when the header is numeric, a tz-aware datetime when it's an HTTP-date, or None when unset. Assign an int / timedelta / datetime to set it; assign None to remove it.

age property writable

age: int | None

The Age header in seconds — RFC 9110 §5.1. None when unset.

cache_control property

cache_control: Any

Parsed Cache-Control header (read-only view).

For setting directives, prefer set_cache_control(...) which writes the header directly. This property is convenient for introspection: resp.cache_control.max_age, resp.cache_control.no_store, etc.

get_json

get_json() -> Any

Parse the response body as JSON.

Returns None for an empty body. Useful in tests to inspect a JSON response without re-decoding body by hand. Raises if the body is non-empty and not valid JSON.

encode

encode() -> bytes

Encode to raw HTTP/1.1 bytes — called once, cached.

set_cookie(key: str, value: str, max_age: Any = None, expires: Any = None, path: str = '/', domain: str | None = None, secure: bool = False, httponly: bool = False, samesite: str | None = 'Lax', partitioned: bool = False) -> None

Build a Set-Cookie header per RFC 6265.

samesite defaults to "Lax" — a CSRF-resistant default that matches modern browser behaviour. Pass samesite="None" (with secure=True) for a cookie that must travel on cross-site requests, or samesite=None/"" to omit the attribute.

expires= accepts a datetime, a Unix timestamp int|float, or an already-formatted IMF-fixdate str. When both max_age and expires are set, both are emitted (RFC 6265 §5.2.2: clients prefer Max-Age when supported, falling back to Expires on legacy IE).

partitioned=True adds the CHIPS Partitioned attribute (Cookies Having Independent Partitioned State) — a partitioned cookie is keyed to the top-level site, so embedded third-party contexts each get an isolated jar. Partitioned requires Secure, so it is only emitted when secure=True.

The cookie name and value are rejected if they contain CR, LF, or NUL — untrusted data must not be able to inject additional cookies or response headers.

calculate_content_length

calculate_content_length() -> int

Set Content-Length from len(body) and return the value.

Useful when a caller mutates body directly and wants the header to follow. The ASGI emit path computes Content-Length from body on the fly anyway; this helper is for callers that want it locked into self.headers ahead of time.

set_data

set_data(value: bytes | str) -> None

Replace the response body.

Accepts bytes or str (UTF-8 encoded). Invalidates the cached HTTP/1.1 encode so the new body wire-out on the next emit. Refreshes Content-Length when previously set on the headers.

set_cache_control

set_cache_control(max_age: int | None = None, public: bool = False, private: bool = False, no_cache: bool = False, no_store: bool = False, must_revalidate: bool = False, immutable: bool = False, s_maxage: int | None = None) -> str

Build and set the Cache-Control header — RFC 9111 §5.2.

Combines the standard directives in the order RFC 9111 §5.2 documents. Values that are False / None are omitted, so a plain resp.set_cache_control(max_age=3600, public=True) produces Cache-Control: public, max-age=3600. Returns the value set.

add_vary

add_vary(*header_names: str) -> str

Append header names to the Vary response header — RFC 9110 §12.5.5.

Merges with any existing Vary value (de-duplicates, case-insensitive). Returns the resulting header value. Useful when middleware wants to communicate "this response depends on the named request headers" without clobbering existing entries.

set_basic_auth_challenge

set_basic_auth_challenge(realm: str = 'Authentication Required') -> str

Write a Basic WWW-Authenticate challenge — RFC 7617.

Convenience for the common 401 case: WWW-Authenticate: Basic realm="<realm>", charset="UTF-8". Returns the header value written.

set_content_range

set_content_range(start: int | None, stop: int | None, length: int | None, unit: str = 'bytes') -> str

Write a Content-Range header — RFC 9110 §14.4.

  • set_content_range(0, 499, 1234)bytes 0-499/1234.
  • start/stop both None → an unsatisfied-range response: bytes */1234 (length required in that form).
  • length None → unknown total: bytes 0-499/*.

Returns the header value written.

set_etag

set_etag(etag: str, weak: bool = False) -> None

Set the ETag header from an explicit value.

Quotes the value if the caller passed it bare. Prepends W/ when weak=True. Use add_etag() for body-derived MD5 ETags; set_etag is for callers that already have an authoritative tag (DB revision, commit hash, version counter).

get_etag

get_etag() -> tuple[str | None, bool]

Return (etag, is_weak) parsed from the ETag header.

(None, False) when unset. Returned tag keeps its quotes so it compares directly with If-None-Match values.

freeze

freeze() -> None

Pre-compute the cached HTTP/1.1 encode.

For buffered responses, populates _encoded so subsequent access pays no encode cost. For streaming responses, no-op. Used by response caching layers that want immutable bytes.

iter_encoded

iter_encoded() -> Any

Yield the response body.

Buffered → single-chunk iter over body. Streaming → proxy to the underlying async iterator. Lets callers drain a response without going through ASGI emit.

iter_chunked

iter_chunked(size: int) -> Any

Yield the response body in fixed-size chunks.

Buffered responses are split into size-byte slices (final slice may be shorter). Streaming responses are returned unchanged — the chunk boundaries are then controlled by the underlying generator, not the caller. size must be positive.

add_etag

add_etag(weak: bool = False) -> str

Compute and attach an ETag derived from the body.

Uses MD5 of the response body, opaque-quoted per RFC 9110 §8.8.3. weak=True prepends W/ so the validator is treated as a weak match (matching content but possibly different byte-for-byte). Sets ETag even if one was already set; pass the explicit ETag in __init__(headers=...) to skip this. Returns the value set.

make_conditional

make_conditional(request: Any) -> Response

Downgrade this response to 304 when the request's preconditions match the response's ETag / Last-Modified.

Checks If-None-Match first (per RFC 9110 §13.2 precedence), then If-Modified-Since. On a match, mutates self to status 304 with no body. Returns self so callers can use it inline: return resp.make_conditional(request).

Handles If-None-Match: * (matches any current representation of the resource) and the weak/strong ETag comparison rules.

set_content_disposition

set_content_disposition(disposition: str = 'attachment', filename: str | None = None) -> str

Write a Content-Disposition header — RFC 6266.

disposition is "attachment" (force download) or "inline" (render in-browser). When filename is given it is added as the filename parameter; non-ASCII names also get the RFC 5987 filename*=UTF-8''… form for modern browsers. Returns the header value written.

delete_cookie(key: str, path: str = '/', domain: str | None = None, secure: bool = False, httponly: bool = False, samesite: str | None = None) -> None

Delete a cookie by overwriting it with an empty value + Max-Age=0.

The browser only treats the new cookie as a replacement for the existing one if Path, Domain, and the Secure / SameSite attributes match — otherwise it stores both. So a session cookie originally set with Secure; SameSite=None will not be deleted by a plain delete_cookie(key) call. Pass the same flags here.

StreamingResponse

Bases: Response

Streaming response for large payloads.

content may be an async iterator/iterable or a plain sync iterable (e.g. a generator). A sync iterable is wrapped so the response always exposes an async stream; both forms are accepted.

encode

encode() -> bytes

For streaming, encode headers with chunked transfer.

stream_to async

stream_to(transport: Any) -> None

Stream chunks to transport.

UJSONResponse

Bases: Response

JSON response encoded with ujson.

Lazily imports ujson at construction. Raises ImportError with a clear message when the package is missing rather than at module load, so apps that don't use this class don't need ujson installed.

RequestMetrics

A finished HTTP request, as seen by an instrumentation hook.

route is the matched route's path template (/items/{id}), which is safe to use as a metric label; it is None whenever no route+method pair matched — both a 404 (no such path) and a 405 (the path exists but the method is not allowed). Group by (route, status_code) to keep those apart. path is the concrete request path and is high-cardinality — prefer route for aggregation.

Markup

Bases: str

A string flagged as already HTML-safe.

Equivalent to markupsafe.Markup for the subset Veloce's templating rely on. Concatenation with a non-Markup string escapes the other operand first so an injection cannot sneak in via +.

BaseHTTPMiddleware

Class-based dispatch-shape middleware.

Subclass and override dispatch:

class TimingMW(BaseHTTPMiddleware):
    async def dispatch(self, request, call_next):
        start = time.perf_counter()
        response = await call_next(request)
        response.headers["X-Elapsed-ms"] = str(
            int((time.perf_counter() - start) * 1000)
        )
        return response

app.add_http_middleware(TimingMW())

For one-off middleware, construct with dispatch=fn instead of subclassing:

async def my_dispatch(request, call_next): ...
app.add_http_middleware(BaseHTTPMiddleware(dispatch=my_dispatch))

The instance is callable as (request, call_next) -> response, so it composes with the existing @app.middleware("http") chain.

dispatch async

dispatch(request: Request, call_next: CallNext) -> Response

Override this in subclasses. Default just calls through.

Implementations must await call_next(request) exactly once to reach the wrapped handler.

CORSMiddleware

Bases: Middleware

Cross-Origin Resource Sharing middleware.

CSRFMiddleware

Bases: Middleware

Double-submit-cookie CSRF middleware.

GZipMiddleware

Bases: Middleware

GZip compression for responses above a size threshold.

Compression runs in the thread pool executor to avoid blocking the event loop.

HTTPSRedirectMiddleware

Bases: Middleware

Redirect HTTP requests to HTTPS.

Resolves the request scheme in this order
  1. ASGI scope "scheme" if set to "https"/"wss" (the server already terminated TLS).
  2. X-Forwarded-Proto header (when a ProxyFix-style middleware ran upstream this is already the trusted value).
  3. Default http.

Uses 308 Permanent Redirect (RFC 9110 §15.4.9) so non-GET methods preserve their method and body. The earlier 301 form was wrong for POST/PUT callers — those would silently become GET.

LoggingMiddleware

Bases: Middleware

Structured request/response access logging.

Middleware

Base middleware class. Subclass and override process_request/process_response.

process_request async

process_request(request: Request) -> Response | None

Called before route handler. Return a Response to short-circuit.

process_response async

process_response(request: Request, response: Response) -> Response

Called after route handler. Can modify the response.

ProxyFix

Bases: Middleware

Reverse-proxy header trust middleware.

Parameters:

Name Type Description Default
x_for int

trust this many hops in X-Forwarded-For (right-to-left).

1
x_proto int

same for X-Forwarded-Proto.

1
x_host int

same for X-Forwarded-Host.

0
x_port int

same for X-Forwarded-Port.

0
x_prefix int

same for X-Forwarded-Prefix.

0
trust_forwarded bool

if True, parse RFC 7239 Forwarded: first; fall back to X-Forwarded-* if absent. Default True.

True

Setting any field to 0 disables it. Negative values raise at construction.

RateLimitMiddleware

Bases: Middleware

Simple in-memory token-bucket rate limiter.

RequestIDMiddleware

Bases: Middleware

Assign a unique request ID to each request and echo it in the response.

SecurityHeadersMiddleware

Bases: Middleware

Attach common hardening response headers to every response.

Set by default:

  • X-Content-Type-Options: nosniff — stop MIME sniffing.
  • X-Frame-Options: DENY — block framing (clickjacking).
  • Referrer-Policy: strict-origin-when-cross-origin.

Off unless configured:

  • Strict-Transport-Security — pass hsts_max_age (seconds). Browsers honour HSTS only over HTTPS, so it is inert in plain-HTTP development, but it is still opt-in because it pins clients to HTTPS for the configured lifetime.
  • Content-Security-Policy — pass content_security_policy.
  • Permissions-Policy — pass permissions_policy.

A header a handler already set on the response is left untouched — these are defaults, not overrides.

ServerSessionMiddleware

Bases: Middleware

Server-side session — the cookie carries only an opaque session id.

The session payload lives in a SessionStore, not in the cookie, so a session is revocable: empty it in a handler (session.clear()) or delete it straight from the store (await store.delete(session_id)) and it is gone server-side. A tampered or stale cookie simply fails to resolve to a stored payload and is treated as a fresh session.

The default store is a process-local InMemorySessionStore; pass a shared backend (e.g. a Redis-backed SessionStore) for a multi-worker deployment. The store is a plain object the caller owns — keep a reference to it to revoke sessions by id.

SessionMiddleware

Bases: Middleware

Server-side session stored in a signed, timestamped cookie.

TrustedHostMiddleware

Bases: Middleware

Validates Host header against an allow-list.

Supports literal hostnames, the catch-all *, and subdomain wildcards of the form *.example.com (matches api.example.com, a.b.example.com, etc. — never the bare example.com). Matching is case-insensitive; the port portion of Host: is stripped before comparison (RFC 9110 §7.2).

is_host_allowed

is_host_allowed(host: str) -> bool

Whether host (bare hostname, no port) passes the allow-list.

Public so the WebSocket dispatch path can apply the same check — a WebSocket handshake never reaches an HTTP middleware's process_request.

WebSocketOriginMiddleware

Bases: Middleware

Reject cross-site WebSocket handshakes (CSWSH).

A WebSocket handshake is not subject to the Same-Origin Policy and bypasses CORS entirely, so a page on any origin can open a socket to your app unless the handshake Origin is checked. Register this with the origins your own front-end is served from; a handshake whose Origin is present but unlisted is refused with close code 1008.

Browsers always send Origin on a WebSocket handshake (RFC 6455 §4.1), so allow_missing=True (the default) still blocks every browser-driven CSWSH attempt while leaving non-browser clients (mobile apps, service-to-service) — which legitimately omit Origin — able to connect. Set allow_missing=False to additionally refuse handshakes that carry no Origin at all.

Plain HTTP requests pass straight through — Origin enforcement for HTTP is CORSMiddleware's job.

is_websocket_origin_allowed

is_websocket_origin_allowed(origin: str) -> bool

Whether a handshake carrying origin may proceed.

Public so the WebSocket dispatch path can apply the check — a handshake never reaches an HTTP middleware's process_request.

Body

Bases: _ParamBase

Request body parameter declaration.

Cookie

Bases: _ParamBase

Cookie parameter declaration.

File

Bases: _ParamBase

File upload parameter declaration.

Form

Bases: _ParamBase

Form field parameter declaration.

Header

Bases: _ParamBase

HTTP header parameter declaration.

Path

Bases: _ParamBase

Path parameter declaration.

Query

Bases: _ParamBase

Query parameter declaration.

Router

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

add_route

add_route(path: str, handler: RouteHandler, methods: list[str], dependencies: list | None = None, response_model: Any = None, tags: list[str] | None = None, summary: str | None = None, name: str | None = None, description: str | None = None, deprecated: bool = False, response_description: str = 'Successful Response', status_code: int = 200, response_class: Any = None, response_model_include: set[str] | None = None, response_model_exclude: set[str] | None = None, response_model_exclude_unset: bool = False, response_model_exclude_defaults: bool = False, response_model_by_alias: bool = False, response_model_exclude_none: bool = False, include_in_schema: bool = True, responses: dict[int, dict[str, Any]] | None = None, operation_id: str | None = None, openapi_extra: dict[str, Any] | None = None, defaults: dict[str, Any] | None = None, callbacks: dict[str, Any] | None = None, strict_slashes: bool | None = None, subdomain: str | None = None, host: str | None = None) -> 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 against the radix tree. O(k) where k = path depth.

get_allowed_methods

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

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

route

route(path: str, methods: list[str] | None = None, dependencies: list | None = None, response_model: Any = None, tags: list[str] | None = None, summary: str | None = None, name: str | None = None, description: str | None = None, deprecated: bool = False, response_description: str = 'Successful Response', status_code: int = 200, response_class: Any = None, response_model_include: set[str] | None = None, response_model_exclude: set[str] | None = None, response_model_exclude_unset: bool = False, response_model_exclude_defaults: bool = False, response_model_by_alias: bool = False, response_model_exclude_none: bool = False, include_in_schema: bool = True, responses: dict[int, dict[str, Any]] | None = None, operation_id: str | None = None, openapi_extra: dict[str, Any] | None = None, defaults: dict[str, Any] | None = None, callbacks: dict[str, Any] | None = None, strict_slashes: bool | None = None, subdomain: str | None = None, host: str | None = None) -> Callable

Generic route decorator.

trace

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

TRACE route decorator — RFC 9110 §9.3.8.

websocket

websocket(path: str) -> Callable

WebSocket route decorator.

add_websocket_route

add_websocket_route(path: str, handler: RouteHandler) -> None

Imperative WebSocket route registration — 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

the imperative imperative WebSocket route registration.

Mirrors add_api_route for WebSocket endpoints — the non-decorator form of @app.websocket(path). name is accepted but currently unused.

add_api_route

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

Imperative route registration.

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.

include_router

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

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

APIKeyCookie

API Key authentication via cookie.

APIKeyHeader

API Key authentication via HTTP header.

APIKeyQuery

API Key authentication via query parameter.

HTTPBasic

HTTP Basic authentication — extracts username:password from Authorization header.

HTTPBasicCredentials

HTTP Basic auth credentials.

HTTPBearer

HTTP Bearer token authentication.

HTTPDigest

HTTP Digest authentication — RFC 7616.

Parses the Authorization: Digest … header into the named fields and returns them as HTTPDigestCredentials. This class does NOT validate the response hash — the application owns the secret (HA1) and must compute the expected digest itself; Digest's whole point is that the secret never crosses the wire. Veloce's job is to parse the challenge response and to emit a 401 + WWW-Authenticate: Digest … header when auth is missing or malformed.

The scheme's responsibility is the parse + challenge dance; verifying the response is application logic.

HTTPDigestCredentials

Parsed Digest auth challenge response — RFC 7616 §3.4.

OAuth2AuthorizationCodeBearer

OAuth2 Authorization-Code (with PKCE) Bearer flow.

Extracts a Bearer token from the Authorization: header exactly like OAuth2PasswordBearer; the difference is the OpenAPI security scheme it advertises (authorizationUrl + tokenUrl + scopes), which is what an interactive OAuth2 client (Swagger UI's "Authorize" button, an SPA's auth library) uses to start the redirect dance.

The construction shape is chosen so an OpenAPI snippet generated from a standard OpenAPI document can be replayed against veloce without rewrites:

oauth2 = OAuth2AuthorizationCodeBearer(
    authorizationUrl="https://auth.example.com/authorize",
    tokenUrl="https://auth.example.com/token",
    refreshUrl=None,
    scopes={"read:items": "Read items", "write:items": "Write items"},
    auto_error=True,
)

OAuth2PasswordBearer

OAuth2 Password Bearer flow — extracts token from Authorization header.

OAuth2PasswordRequestForm

OAuth2 password request form data.

OAuth2PasswordRequestFormStrict

Bases: OAuth2PasswordRequestForm

OAuth2PasswordRequestForm with a mandatory grant_type.

the non-strict form leaves grant_type optional; the strict form requires it and constrains the value to the literal password (RFC 6749 §4.3.2). Missing or mismatched values fail validation with 422.

OpenIdConnect

OpenID Connect Bearer authentication.

Same Bearer extraction logic as the OAuth2 schemes; the OpenAPI scheme advertises a single openIdConnectUrl pointing at the provider's .well-known/openid-configuration document. Clients auto-discover everything else from there.

InMemorySessionStore

Bases: SessionStore

A process-local SessionStore — a dict with per-entry expiry.

Fine for a single-process app and for tests. It does not share state across workers, so a multi-worker deployment needs a shared backend (e.g. Redis) implementing the SessionStore interface.

Session

Bases: dict[str, Any]

The request session — a dict that knows when it has changed.

permanent property writable

permanent: bool

Whether the session cookie should use the longer lifetime.

backed by the reserved _permanent key, so the flag persists in the cookie across requests and toggling it counts as a session mutation.

regenerate_id

regenerate_id() -> None

Request a fresh server-side session id on the next response.

Call this at a privilege boundary — login, role change — so a pre-existing (possibly attacker-planted) session id cannot be replayed against the now-elevated session: the session-fixation defence. It marks the session modified so the rotation is written back. Harmless with cookie-only sessions, which carry no server-side id to rotate.

SessionStore

Server-side session backend interface.

A concrete store persists session payloads keyed by an opaque session id; ServerSessionMiddleware drives it. The methods are async so a network-backed store (Redis, a database) can implement them without blocking the event loop — the bundled InMemorySessionStore satisfies the contract without any real awaiting.

read async

read(session_id: str) -> dict[str, Any] | None

Return the stored payload for session_id, or None when it is absent, expired, or has been revoked.

write async

write(session_id: str, data: dict[str, Any], max_age: int) -> None

Persist data under session_id, to expire after max_age seconds.

delete async

delete(session_id: str) -> None

Revoke session_id — a later read of it must return None.

replace async

replace(session_id: str, data: dict[str, Any], max_age: int) -> bool

Write data for session_id only if it still exists.

Returns True on success, False when the id is absent — it was revoked or expired. This is the race-safe write the middleware uses for an already-stored session, so a request still in flight cannot resurrect a session a concurrent delete removed.

The default is a non-atomic read-then-write; a store with an atomic conditional write (Redis SET ... XX, a DB UPDATE) should override this to close the check-then-write window.

BadData

Bases: BadSignature

The token's payload could not be decoded (malformed base64 / JSON).

BadSignature

Bases: Exception

The token's signature did not verify against the configured secret.

BadTimeSignature

Bases: BadSignature

The signature verified but the token is older than max_age.

Signer

HMAC-SHA256 signer for arbitrary JSON-serialisable values.

Usage

s = Signer(secret="server-secret", salt="reset-token") token = s.dumps({"user_id": 42}) ... data = s.loads(token, max_age=3600) # raises if older than 1h

add_fallback_secret

add_fallback_secret(secret: str | bytes, salt: str | bytes = 'veloce.signing') -> None

Add an additional secret accepted for verification (not signing).

Used during secret rotation: configure the new secret as primary, keep the old one as a fallback for the rotation window. Tokens signed with the fallback still verify; new tokens use the primary.

dumps

dumps(data: Any) -> str

Serialise data to a signed, timestamped, URL-safe token.

loads

loads(token: str, max_age: int | None = None) -> Any

Verify token and return the original data.

Raises BadSignature on tamper / unknown secret, BadTimeSignature when max_age is set and the token's timestamp is older than that.

EventSourceResponse

Bases: Response

SSE streaming response — sends events over a long-lived connection.

Usage

@app.get("/events") async def events(request: Request): async def generate(): for i in range(10): yield ServerSentEvent(data=f"Event {i}") await asyncio.sleep(1) return EventSourceResponse(generate())

stream_to async

stream_to(transport: Any) -> None

Stream SSE events to transport.

ServerSentEvent

A single SSE event.

AsyncTestClient

Async in-memory test client — drives the app through its ASGI surface.

The async counterpart of TestClient: used as an async context manager inside an async test, so each request is awaited on the test's own running event loop instead of through a private loop. The request methods (get / post / …) are coroutines.

async with AsyncTestClient(app) as client:
    resp = await client.get("/")

Cookie persistence, redirect following, and the JSON / form / files body shapes match TestClient exactly. WebSocket testing stays on the sync TestClient.websocket_connect.

cookies property

cookies: _TestClientCookies

Live view of the client's cookie jar (see TestClient.cookies).

set_cookie(key: str, value: str) -> None

Add or update a cookie sent on every subsequent request.

delete_cookie(key: str) -> None

Remove a cookie from the jar. No-op if not present.

request async

request(method: str, path: str, json: Any = None, data: dict[str, str] | None = None, headers: dict[str, str] | None = None, content: bytes | None = None, files: dict[str, Any] | None = None, params: dict[str, str] | Sequence[tuple[str, str]] | None = None, follow_redirects: bool | None = None) -> TestResponse

Generic verb-agnostic request dispatcher (see TestClient.request).

TestClient

Sync test client — drives the app through its ASGI surface.

cookies property

cookies: _TestClientCookies

Live view of the client's cookie jar.

Supports dict-like access (client.cookies["session"]), assignment (client.cookies["k"] = "v"), deletion, iteration, and bulk clear(). Cookies the server sends on responses are automatically merged in via _update_cookies. The state persists across calls until the client is closed.

set_cookie(key: str, value: str) -> None

Add or update a cookie sent on every subsequent request.

delete_cookie(key: str) -> None

Remove a cookie from the jar. No-op if not present.

session_transaction

session_transaction() -> Any

Mutate the session outside a request.

Yields a Session dict pre-loaded from the current session cookie (if any). On block exit the session is re-signed with the app's SessionMiddleware secret and stored in the cookie jar, so the next request carries it::

with client.session_transaction() as sess:
    sess["user_id"] = 7

Raises RuntimeError if the app has no SessionMiddleware.

request

request(method: str, path: str, json: Any = None, data: dict[str, str] | None = None, headers: dict[str, str] | None = None, content: bytes | None = None, files: dict[str, Any] | None = None, params: dict[str, str] | Sequence[tuple[str, str]] | None = None, follow_redirects: bool | None = None) -> TestResponse

Generic request dispatcher — httpx/test-client shape.

client.request("PATCH", "/x", json=...) is the verb-agnostic form of client.get / client.post / …. Bodies (json / data / content / files) and params are handled exactly as the per-verb methods do.

websocket_connect

websocket_connect(path: str, subprotocols: list[str] | None = None, headers: dict[str, str] | None = None) -> _WebSocketSession

Open an in-memory WebSocket against the app — context manager.

Drives the ASGI websocket protocol: synthesise the scope, send websocket.connect, route to the handler, then forward send_text / receive_text / close calls to the running handler through a pair of asyncio queues.

close

close() -> None

Run shutdown lifecycle and close the loop if we own it.

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.

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.

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.

dispatch_request async

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

Handle the request — subclasses must override.

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.

EventLoopWatchdog

Detects event-loop stalls and reports the blocked stack.

A heartbeat callback re-arms itself on the loop every interval seconds; a separate daemon thread measures how long it has been since the last heartbeat while the loop is running. When that gap exceeds stall_threshold something is blocking the loop, and the watchdog logs a warning with the loop thread's current stack plus a prescriptive hint (blocking-I/O versus CPU-bound).

Each distinct stall is reported once — the heartbeat counter is frozen for the stall's whole duration, and the watch thread reports a given counter value at most once.

start

start() -> None

Arm the watchdog. Must be called from inside the loop thread.

stop

stop() -> None

Disarm the watchdog and join its thread. Safe to call twice.

WebSocket

WebSocket connection handler.

query_params property

query_params: Any

Parsed query string of the WebSocket handshake URL.

Read it as ws.query_params["token"]. Backed by QueryParams (multi-value, getlist-aware). Empty when the scope carries no query_string.

url property

url: str

The WebSocket handshake URL path — ASGI-style shape.

Returns path plus ?query when a query string is present.

client property

client: Any

The connecting peer as an Address(host, port).

Reads scope["client"] (the ASGI (host, port) pair). Returns None when the scope carries no client info.

state property

state: Any

Per-connection scratch namespace.

Lazily-created State (a dict subclass) supporting both ws.state.user = ... attribute access and ws.state["user"].

cookies property

cookies: dict[str, str]

Cookies sent with the WebSocket handshake.

Parses the handshake Cookie header into {name: value}. Empty when no cookie header was present.

application_state property

application_state: WebSocketState

Server-side state of the WebSocket.

  • CONNECTING before the app sends accept().
  • CONNECTED after accept() and until close() is sent.
  • DISCONNECTED after close() (locally) or after the peer half-closes (observed via WebSocketDisconnect).

client_state property

client_state: WebSocketState

Client-side state of the WebSocket.

Veloce does not distinguish the two halves at the protocol level beyond the close flag, so this mirrors application_state once the peer disconnects and otherwise stays CONNECTED once the handshake completes.

origin property

origin: str | None

The client-supplied Origin header, or None if absent.

WebSocket handshakes carry Origin per RFC 6455 §10.2 / §4.1. Browsers always send it; non-browser clients may omit it. The header is the application's primary defence against Cross-Site WebSocket Hijacking — CSWSH bypasses CORS because the handshake is plain HTTP/1.1 and Same-Origin Policy does not apply to it. Pair this accessor with check_origin(allowed) before accept().

requested_subprotocols property

requested_subprotocols: list[str]

Subprotocols the client offered in Sec-WebSocket-Protocol.

Returns them in client preference order (RFC 6455 §1.9). Empty list when the header is absent. Whitespace around each token is stripped; the comparison the negotiator performs is case-sensitive per the spec.

from_asgi classmethod

from_asgi(scope: dict, receive: Any, send: Any) -> WebSocket

Construct an ASGI-driven WebSocket (no asyncio.Transport).

Used by Veloce.__call__ for scope["type"] == "websocket". Headers come from scope["headers"] (list of (bytes, bytes)), decoded latin-1 per ASGI. accept/send_*/receive_*/close all dispatch through send/receive instead of the raw frame writer used by the asyncio.Transport mode.

check_origin

check_origin(allowed: str | Iterable[str]) -> bool

Return True when the handshake's Origin is in allowed.

Pass a single origin string or an iterable of allowed origins (e.g. ["https://app.example.com", "https://admin.example.com"]). Normalisation matches WebSocketOriginMiddleware: each side is lowercased and has any trailing slash stripped, so allow-lists written for one API are interchangeable with the other.

  • Wildcard. "*" in allowed accepts any origin and is the opt-in "I have my own check elsewhere" escape hatch — the symmetric behaviour to WebSocketOriginMiddleware's allowed_origins=["*"].
  • Missing Origin (no header at all, or a literal Origin: null from a sandboxed iframe / file:// page) is a non-match and returns False. Non-browser clients legitimately omit the header — if you want to allow them, branch on ws.origin is None explicitly. The WebSocketOriginMiddleware middleware path also offers an allow_missing=True switch; this in-handler helper is deliberately strict-by-default.
Usage

@app.websocket("/ws") async def chat(ws: WebSocket): if not ws.check_origin("https://app.example.com"): await ws.close(code=1008) # policy violation return await ws.accept() ...

For the middleware-style check (registered once, runs before the handler) reach for veloce.SecurityHeadersMiddleware's sibling WebSocketOriginMiddleware.

negotiate_subprotocol

negotiate_subprotocol(supported: list[str]) -> str | None

Pick the first client-offered subprotocol that the server supports.

Per RFC 6455 §4.1, the server picks ONE protocol from the client's list. Most servers prefer to honour the client's preference order (first match wins), which is what we do.

accept async

accept(subprotocol: str | None = None, headers: dict[str, str] | None = None) -> None

Complete the WebSocket handshake.

send_text async

send_text(data: str) -> None

Send a text frame.

send_json async

send_json(data: Any, mode: str = 'text') -> None

Send JSON data.

mode="text" (default) wraps the JSON in a text frame (opcode 0x1). mode="binary" sends the raw JSON bytes as a binary frame (0x2).

send_bytes async

send_bytes(data: bytes) -> None

Send a binary frame.

receive async

receive() -> dict

Receive a raw ASGI WebSocket message.

Returns the message dict as the ASGI server delivered it ({"type": "websocket.receive", "text"/"bytes": ...}). A websocket.disconnect message raises WebSocketDisconnect. ASGI-mode only — raw asyncio-transport connections don't carry ASGI message envelopes.

The same handshake state machine the typed receive_* helpers enforce: the raw escape hatch must not be a way around receive-before-accept or receive-after-close (which would consume the websocket.connect envelope and corrupt the next accept()).

send async

send(message: dict) -> None

Send a raw ASGI WebSocket message.

message is forwarded straight to the ASGI send callable, e.g. {"type": "websocket.send", "text": "..."}.

receive_text async

receive_text(timeout: float | None = None) -> str

Receive a text message. Raises asyncio.TimeoutError if timeout exceeded.

receive_json async

receive_json(timeout: float | None = None) -> Any

Receive and parse JSON.

receive_bytes async

receive_bytes(timeout: float | None = None) -> bytes

Receive binary data. Raises asyncio.TimeoutError if timeout exceeded.

iter_text async

iter_text() -> Any

Async-iterate over incoming text frames until the peer closes.

Usage

async for msg in ws.iter_text(): ...

Terminates cleanly on WebSocketDisconnect. Other exceptions propagate.

iter_bytes async

iter_bytes() -> Any

Async-iterate over incoming binary frames until the peer closes.

iter_json async

iter_json() -> Any

Async-iterate over incoming JSON-decoded frames until peer closes.

close async

close(code: int = 1000, reason: str = '') -> None

Send a close frame.

Per RFC 6455 §5.5.1 the close-frame payload is a 2-byte big-endian status code optionally followed by a UTF-8 reason of at most 123 bytes (so the whole payload fits in the 125-byte control-frame budget). Reasons longer than 123 bytes are truncated to a clean UTF-8 boundary.

feed_data

feed_data(data: bytes) -> None

Feed one raw WebSocket frame from the transport (called by the protocol).

Handles fragmented messages (RFC 6455 §5.4): a data frame with FIN=0 opens a message that subsequent continuation frames (opcode 0x0) extend, and the FIN=1 continuation completes it. Control frames (close / ping / pong) are never fragmented and may be interleaved within a fragmented message without disturbing the reassembly buffer.

render_template

render_template(template_name: str, **context: Any) -> str

Render a named template against the current app.

Pulls the Jinja2Templates instance off current_app._templates (set when the user constructs a Jinja2Templates(templates_dir) and assigns it). Raises RuntimeError outside a request / app context. Returns the rendered string; callers wrap in a Response themselves if they need one.

render_template_string

render_template_string(source: str, **context: Any) -> str

Render an inline string template against the current app.

Builds a transient Jinja2 environment when no Jinja2Templates is bound on the app, so the helper works for one-off templates that don't need a templates directory. Honours app-level filters / globals / tests and context processors when the env is reachable via app._templates.

jsonable_encoder

jsonable_encoder(obj: Any, include: set[str] | None = None, exclude: set[str] | None = None, exclude_unset: bool = False, exclude_defaults: bool = False, exclude_none: bool = False) -> Any

Convert complex objects to JSON-serializable types.

Handles Pydantic models, dataclasses, datetime, Decimal, UUID, Enum, Path, sets, frozensets, generators, and nested structures.

include / exclude apply to dict keys at every depth — passing exclude={"password"} strips a password key wherever it appears in the structure, not only at the top level.

Usage

data = jsonable_encoder(my_pydantic_model, exclude={"password"})

abort

abort(status_code: int, detail: str = '', headers: dict[str, str] | None = None) -> NoReturn

Raise an HTTPException — a concise shorthand.

Raises the typed subclass for known status codes (e.g. NotFound for 404, Forbidden for 403) so error handlers registered against a specific subclass match. Unknown codes fall back to the bare HTTPException.

Usage

abort(404) # → raises NotFound abort(403, "Forbidden") # → raises Forbidden

after_this_request

after_this_request(func: Any) -> Any

Register a one-shot after-request callback.

Fires after the global @app.after_request hooks have run for the current request only — future requests are unaffected. Useful for work that depends on data computed inside the handler (e.g. setting a cookie whose value the handler decided).

Returns the callback unchanged so it can be used as a decorator. Raises RuntimeError when called outside an active request.

flash

flash(message: str, category: str = 'message') -> None

Flash a message for the next request — requires SessionMiddleware.

Usage

flash("Item created successfully") flash("Invalid input", "error")

get_flashed_messages

get_flashed_messages(with_categories: bool = False, category_filter: list[str] | None = None) -> list

Get flashed messages — call in templates.

Usage

messages = get_flashed_messages() messages = get_flashed_messages(with_categories=True)

has_app_context

has_app_context() -> bool

True iff current_app resolves to a real app.

Use this to gate code that reads current_app/app.config so it can also run outside a request (e.g. helper modules imported at module-import time, before any app is bound to the contextvar).

has_request_context

has_request_context() -> bool

True iff a request is bound to this task/context.

Veloce passes the live request through arguments during dispatch, so this only flips True inside app.test_request_context() blocks or when application code explicitly sets the contextvar.

jsonify

jsonify(*args: Any, **kwargs: Any) -> JSONResponse

Create a JSON response — a concise shorthand.

Honours two app-config flags when called inside a request: - JSON_SORT_KEYS (default False) — sort dict keys alphabetically. - JSONIFY_PRETTYPRINT_REGULAR (default False) — indent the output with 2 spaces for readability. Often enabled under DEBUG.

Usage

return jsonify(name="alice", age=30) return jsonify({"name": "alice"}) return jsonify([1, 2, 3])

make_response

make_response(body: Any = b'', status_code: int = 200, headers: dict[str, str] | None = None, content_type: str | None = None) -> Response

Create a Response — a convenience wrapper.

Usage

resp = make_response("Hello", 200) resp = make_response({"data": True}, 201)

redirect

redirect(location: str, code: int = 302, headers: dict[str, str] | None = None) -> Response

Build a redirect response helper.

Default code=302 matches the long-standing convention. RFC 9110 §15.4 catalogue: 301 (permanent, method may change), 302 (found, method may change), 303 (see other, method becomes GET), 307 (temporary, method preserved), 308 (permanent, method preserved). Pick the one that matches your semantics — the helper is a thin wrapper, not a policy. Accepts extra headers (e.g. Vary).

send_file

send_file(path_or_file: Any, mimetype: str | None = None, as_attachment: bool = False, download_name: str | None = None, last_modified: Any = None, etag: bool | str = True, max_age: int | None = None) -> Response

Serve a file top-level helper.

Accepts a filesystem path (str / PathLike) and returns a FileResponse with conditional-GET headers already set (Last-Modified, ETag — both were added by Q40/Q42). Optional knobs:

  • mimetype= overrides the auto-guessed content type.
  • as_attachment=True sets Content-Disposition: attachment; filename=<download_name or basename>.
  • download_name= overrides the filename in Content-Disposition.
  • last_modified= overrides the file's mtime (datetime, unix ts, or pre-formatted IMF-fixdate string).
  • etag=False suppresses the auto-generated ETag; etag="<value>" uses the caller-provided one verbatim (already-quoted).
  • max_age= adds Cache-Control: public, max-age=<n>.

send_from_directory

send_from_directory(directory: str, filename: str, mimetype: str | None = None, as_attachment: bool = False, download_name: str | None = None) -> FileResponse

Send a file from a directory (sync version).

Traversal-safe via safe_join. Returns 403 on any escape attempt.

For async, use send_from_directory_async() instead.

stream_with_context

stream_with_context(generator: Any) -> Any

Keep the request context alive while a streaming generator runs.

A streaming response body is consumed by the ASGI emit layer after the handler has returned, by which point the request context has been torn down — so a generator that touches request, g, or current_app would fail. Wrap it::

return StreamingResponse(stream_with_context(generate()))

The current request / app / g snapshot is captured now and re-established for the lifetime of the wrapped iteration. Accepts either an async or a synchronous generator/iterable.

escape

escape(value: Any) -> Markup

HTML-escape value and wrap in Markup.

Objects that implement __html__() are trusted: their return is wrapped as-is. Otherwise the value is str()-coerced and the five HTML-significant characters are replaced with numeric character references (per WHATWG HTML §13).

hash_password

hash_password(password: str | bytes, method: str = 'scrypt', salt_length: int = _SALT_BYTES) -> str

Derive a salted verifier for password.

Returns a self-describing string of the form method$params$salt$hash where each segment is URL-safe base64 (no padding). Pass this string verbatim to verify_password later.

method: - "scrypt" (default): RFC 7914, memory-hard. - "pbkdf2:sha256": NIST SP 800-132, CPU-only.

salt_length is the number of random bytes used for the salt; 16 is the OWASP minimum.

hash_password_async async

hash_password_async(password: str | bytes, method: str = 'scrypt', salt_length: int = _SALT_BYTES) -> str

Async-safe wrapper for hash_password — runs the KDF on a thread.

hash_password calls hashlib.scrypt / pbkdf2_hmac synchronously; those are deliberately slow (~100 ms) and would block the event loop if called directly from an async handler. This wrapper offloads the work to the default executor so the loop stays free for other requests. Use this from async def handlers; keep the sync hash_password for sync handlers / scripts / CLI tools.

is_strong_password

is_strong_password(password: str, *, min_length: int = 8) -> bool

Cheap policy check — not exhaustive.

Returns True only when the password meets a minimum baseline: at least min_length characters and contains at least one digit AND one alphabetic character. Callers that want NIST SP 800-63B-style policy (block known-leaked passwords, drop max-length caps, etc.) should layer on top.

verify_password

verify_password(stored: str, candidate: str | bytes) -> bool

Compare candidate against a stored verifier string.

Returns False (never raises) for any malformed stored, unknown method, or mismatch. Uses hmac.compare_digest for the final byte comparison so timing attacks can't leak partial matches.

verify_password_async async

verify_password_async(stored: str, candidate: str | bytes) -> bool

Async-safe wrapper for verify_password — runs the KDF on a thread.

Same rationale as hash_password_async: the scrypt / PBKDF2 verify is ~100 ms of CPU; calling it synchronously from an async handler blocks the event loop. Offload it.

constant_time_compare

constant_time_compare(a: str | bytes, b: str | bytes) -> bool

Compare two secrets without leaking their contents through timing.

Use this instead of == when checking a security-sensitive value an attacker controls one side of — an API key, a token, a signature, a CSRF value — so the comparison cannot be turned into a byte-by-byte oracle via response-timing measurement.

Wraps hmac.compare_digest; str inputs are UTF-8 encoded first. Returns False (rather than raising) when the two arguments are not both string-like or not both bytes-like, so a type mismatch is a plain non-match.

References: - CWE-208 (Observable Timing Discrepancy)

safe_join

safe_join(directory: str, *paths: str) -> str | None

Join paths onto directory, returning None on any escape.

Returns the absolute joined path if it equals directory or is a descendant. Returns None if: - any component in paths is an absolute path, - any component contains a NUL byte, - the resolved path is outside directory.

The check is performed via os.path.abspath, which collapses .. segments before comparison. Symlinks are not resolved — callers that distrust symlinks must use os.path.realpath themselves.

secure_filename

secure_filename(name: str) -> str

Return a safe basename for name.

  • Strips directory separators (/, \) and any non-ASCII characters.
  • Replaces unsafe characters with underscores; collapses repeats.
  • Strips leading/trailing dots/spaces/underscores (blocks . and ..).
  • Prefixes Windows reserved names (CON, PRN, …) with _.
  • Returns "" when nothing survives sanitisation.

Empty or whitespace-only input returns "". The caller is responsible for treating that as a rejection — secure_filename will not raise.