Web integration
The route table a web framework mounts, and the request/response types handlers use (see citry.contrib).
URLRoute class
One framework-neutral route: either a handler or nested children.
A child's full path is the parent's path followed by the child's (plain concatenation; end a parent path with /). {name} segments in the path become keyword arguments of the handler.
handler_async optionally carries an async def twin of handler (same signature and behavior). Adapters that run an event loop (ASGI) serve the route through the twin, awaiting it natively, while the plain handler stays what the sync hosts (WSGI, sync Django) mount and run. Only routes that need both worlds carry it; a route table meant solely for ASGI can simply pass an async def function as handler.
Example::
URLRoute("cache/{class_id}.{script_type}", handler=serve_script, name="citry_cached_script")
URLRoute("ext/", children=[URLRoute("my_ext/status", handler=status)])
handler attribute
handler: Callable[..., RouteResponse | Awaitable[RouteResponse]] | None RouteRequest class
A framework-neutral view of one HTTP request, passed to route handlers.
Each web adapter (citry.contrib.asgi, citry.contrib.wsgi, the Django patterns, ...) builds this from its host's request, so a handler reads the same fields no matter which framework serves it. Anything host-specific stays reachable through native.
Attributes
methodstr- The HTTP method, uppercase (`"GET"`, `"POST"`, ...).pathstr- The full URL path of the request, including the prefix the route table is mounted under (e.g. `"/citry/citry.js"`).queryMapping[str, tuple[str, ...]]- The query-string parameters. Each key maps to all values it was sent with, in order, so repeated keys are preserved.headersRouteHeaders- The HTTP request headers; lookups ignore case.bodybytes- The raw request body. Empty for bodyless methods such as GET.content_typestr- The `Content-Type` header value, or `""` when the request names none.nativeAny- The untouched host request object: the ASGI scope, the WSGI environ, or Django's `HttpRequest`.
RouteResponse class
What a route handler returns; adapters translate it to the host's response type.
Attributes
contentstr | bytes- The response body, as text or raw bytes.content_typestr- The `Content-Type` header value to send.statusint- The HTTP status code.headerstuple[tuple[str, str], ...]- Extra response headers, as `(name, value)` pairs; adapters send them in addition to `Content-Type`. A name may repeat (e.g. two `Set-Cookie` lines): the ASGI and WSGI adapters send every pair, while the Django adapter raises `ValueError` on a repeated name, because Django's response object holds one value per header name.
RouteHeaders class
Bases: Mapping
A read-only mapping of HTTP header names to values; lookups ignore case.
Built from (name, value) pairs. Iteration yields the names lowercased, and a header sent multiple times has its values joined with ", " (the HTTP rule for repeatable headers).
Example
headers = RouteHeaders([("Content-Type", "application/json")]) headers["content-type"] # "application/json" headers["CONTENT-TYPE"] # "application/json"