Request
HTTP request handling and utilities.
Transport-agnostic request system.
- Classes:
- BaseRequest (ABC) — transport-agnostic interface
├── HttpRequest — ASGI HTTP (stream-based, body via receive) └── MsgRequest — WSX messages (atomic, WebSocket/NATS)
RequestRegistry — factory and tracking for active requests
Every request has an associated Response (request.response).
The handler returns a value; the app’s handle_request calls
response.set_result() and sends the ASGI response (the server’s
Dispatcher only demultiplexes on the first path segment).
Request/Response lifecycle (inside AsgiApplication.handle_request):
RequestRegistry.create(scope, receive, send)
→ factory() # sync: allocate slots
→ request.init() # async: read body, parse data
→ register in registry
set_current_request(request)
router.node(path) → handler
result = handler(**request.handler_kwargs()) # query + body (body_json/body_raw)
response.set_result(result)
response(scope, receive, send)
set_current_request(None)
registry.unregister()
- Notification pattern (fire-and-forget over HTTP):
Some protocols (e.g., JSON-RPC 2.0) define messages that expect no response payload. The handler sets the status code and returns None; the app sends an empty HTTP response:
request = get_current_request() request.response.status_code = 202 return None # the app sends 202 with empty body
- class genro_asgi.request.BaseRequest[source]
Bases:
ABCAbstract base for transport-agnostic requests.
Subclasses: HttpRequest (ASGI HTTP), MsgRequest (WSX messages). Handlers see only BaseRequest and work identically across transports.
Every instance carries an associated
response(Response object). The handler controls the response viarequest.response: status code, headers, and — indirectly — body (the Dispatcher callsresponse.set_result()with whatever the handler returns).For notification/fire-and-forget over HTTP the handler sets
request.response.status_code = 202and returnsNone.- Abstract properties (subclasses must implement):
id, method, path, headers, cookies, query, data, transport
- Concrete attributes:
response: Associated Response object (created in __init__) auth_tags: Security tags injected by AuthMiddleware via scope env_capabilities: Environment flags injected via scope external_id: Client-provided correlation ID (optional) tytx_mode: True when request uses TYTX serialization tytx_transport: TYTX transport type (‘json’, ‘msgpack’) or None app_name: App handling this request (set after routing, for metrics) created_at: Timestamp (epoch) when request was created age: Seconds since creation (computed)
- add_cleanup(callback)[source]
Register a callback to run at end of request (always, even on error).
- handler_kwargs()[source]
Build the keyword arguments a route handler is called with.
Query params are the base; how the body adds to them follows the content-type, not the Python shape of the decoded value:
application/x-www-form-urlencodedis a set of key/value pairs, the same shape as the query, so its fields are decoded (typed, via TYTXfrom_qs) and merged in — the body wins on a name clash;a hydrated body (JSON/XML/msgpack, decoded by TYTX) is passed whole as
body_data— a structured payload, one argument, never unpacked into parameters (so a model-typed handler binds it cleanly);any other body (opaque bytes) is passed as
body_raw;an empty body adds neither key.
Only the form merges — it alone is parameter-shaped. The router drops whichever key the handler does not declare.
- abstractmethod async init(scope, receive, send=None, **kwargs)[source]
Async initialization — parse transport data from ASGI scope.
Subclasses must override to read body/message, populate internal state (headers, cookies, query, data), and extract auth context.
- Parameters:
scope (
MutableMapping[str,Any]) – ASGI scope dict.receive (
Callable[[],Awaitable[MutableMapping[str,Any]]]) – ASGI receive callable.send (
Optional[Callable[[MutableMapping[str,Any]],Awaitable[None]]]) – ASGI send callable (optional, not used by all transports).**kwargs (
Any) – Transport-specific options (e.g.server,websocket).
- Return type:
- run_cleanups(error=None)[source]
Run registered callbacks. Called by Dispatcher in finally block.
- Parameters:
error (
BaseException|None) – The exception if request failed, None on success.- Return type:
- class genro_asgi.request.HttpRequest[source]
Bases:
ScopeConnectionMixin,BaseRequestHTTP request adapter — wraps ASGI scope, parses body via asgi_data.
Supports both TYTX-encoded requests (type hydration for Decimal, date, datetime, time) and standard HTTP requests with plain JSON bodies.
TYTX mode is detected from the
X-TYTX-Transportheader. When present, Response uses the same transport to serialize the reply. Body parsing is handled bygenro_tytx.asgi_data()in both cases (after genro-tytx 0.8.0, plain JSON is parsed correctly without TYTX markers).- Parsing flow (in
init()): Headers decoded from ASGI scope (latin-1)
TYTX mode detected from X-TYTX-Transport header
asgi_data(scope, receive)parses headers, query, cookies, bodyRequest ID extracted from x-request-id header or generated (UUID)
Auth context read from scope (injected by AuthMiddleware)
- Body availability:
asgi_dataconsumes the ASGI receive callable and never discards the payload: the decoded value (or the raw bytes, for content types it cannot hydrate) is available asself.data. Only thebodyproperty returnsb""(the raw stream is not kept separately).- Extra properties (beyond BaseRequest):
scope, body, scheme, url, headers_obj, query_params, client, state, content_type
- property db: Any
Default db handler, lazy-loaded from
scope["ctx"]._db.On first access, reads
ctx._db(the handler set by the app) and registersdb.closeConnectionas a request cleanup callback.- Returns:
The db handler, or None if ctx is absent or has no
_db.
- get_db(name)[source]
Return a db handler by name, resolved through the app.
Delegates to
ctx.app.get_db(name)(app registry first, then server). Returns None if there is no context app.- Return type:
- property headers_obj: Headers
Request headers as Headers object (case-insensitive).
- async init(scope, receive, send=None, **kwargs)[source]
Async init — parse headers, body, query, cookies via asgi_data.
Delegates to
genro_tytx.asgi_data(scope, receive)which handles TYTX-encoded and plain JSON bodies transparently (since genro-tytx 0.8.0). After this method:self._data: parsed body (hydrated value for JSON/XML/msgpack, raw bytes for content types TYTX cannot hydrate, None if empty)self._headers,self._cookies,self._query: populatedself._tytx_mode: True if X-TYTX-Transport header was presentself._auth_tags,self._env_capabilities: from scopeself._body: b”” (the body lives inself._data— see class docstring)
- Return type:
- property scope: MutableMapping[str, Any]
Raw ASGI scope dict.
- Parsing flow (in
- class genro_asgi.request.MsgRequest[source]
Bases:
BaseRequestMessage-based request adapter (WSX over WebSocket, NATS, etc.).
Parses WSX:// formatted messages into BaseRequest interface. Transport-agnostic: works with any message-based protocol.
- property client: tuple[str, int] | None
Client address as raw (host, port) tuple from WebSocket scope.
Unlike HttpRequest.client (which wraps in Address), WSX messages return the raw tuple because WebSocket connections are long-lived and the overhead of wrapping each message is unnecessary.
- async init(scope, receive, send=None, **kwargs)[source]
Async initialization - parses WSX message.
- Return type:
- property scope: MutableMapping[str, Any]
Access to raw ASGI scope.
- class genro_asgi.request.RequestRegistry(factories=None)[source]
Bases:
objectRegistry for creating and tracking active requests.
Responsibilities: - Creates appropriate request based on scope[“type”] using factories dict - Calls async init() on the created request - Tracks active requests for monitoring and metrics - Provides iteration and lookup by request ID
Example
registry = RequestRegistry() request = await registry.create(scope, receive, send) print(f”Active: {len(registry)}”) registry.unregister()
- async create(scope, receive, send=None, **kwargs)[source]
Create and register a request from ASGI scope.
- Return type:
- property current: BaseRequest | None
Current request from ContextVar.
- factories