Request — Aquilia Documentation
Comprehensive guide and documentation for Request in the Aquilia framework. View API reference, examples, and implementation patterns.
Core Request The Request class is a performance-optimized, class-based HTTP request wrapper built directly on the ASGI scope. It leverages __slots__ for low memory overhead and features lazy, cached property accessors for headers, queries, cookies, and bodies. Request Lifecycle & Architecture The following low-level system design diagram illustrates how an incoming ASGI client payload traverses the lazy-evaluation and protection boundaries: ASGI Entry Raw Connection Scope Security Guards Max Body / ReDoS limit Lazy Parser Cache Headers/Cookies/Body Controller Engine RequestCtx Injection Architecture & Slots To eliminate dictionary overhead, Request uses Python's __slots__ mapping for all internal state fields. class Request: __slots__ = ( "scope", "_receive", "_send", "max_body_size", "max_field_count", "max_file_size", "upload_tempdir", "trust_proxy", "chunk_size", "json_max_size", "json_max_depth", "form_memory_threshold", "state", "_body", "_body_consumed", "_json", "_surp", "_form_data", "_query_params", "_headers", "_cookies", "_url", "_disconnected", "_temp_files", ) Request Faults Request validation and parsing failures trigger structured exceptions mapped to the Aquilia Fault system: Fault Class Fault Code HTTP Status Description , , , , , , , ].map((row, i) => ( ))} Constructor & Config The Request object is initialized with the ASGI scope, receive, and optional send callables: Request( scope: dict, # ASGI scope receive: Callable, # ASGI receive channel send: Callable | None = None, # ASGI send channel (optional) *, max_body_size: int = 10_485_760, # 10 MB body limit max_field_count: int = 1000, # Max form fields max_file_size: int = 2_147_483_648,# 2 GB uploaded file limit upload_tempdir: Path | None = None,# Path for temp files trust_proxy: bool | list[str] = False, # Blanket trust or trusted CIDRs list chunk_size: int = 65536, # Byte streaming chunk size json_max_size: int = 10_485_760, # 10 MB JSON size limit json_max_depth: int = 64, # Max JSON nest depth form_memory_threshold: int = 1048576, # 1 MB memory limit before spilling uploads to disk ) Core Properties & Accessors Attribute Type Description , , , , , , , , , ].map((row, i) => ( ))} Client IP & Proxy Trust The client_ip() method determines the client's IP. When trust_proxy is configured with a list of networks, it walks the X-Forwarded-For list from right to left, returning the rightmost IP that is not in the trusted set to prevent client spoofing. # Initialize with trusted proxy CIDRs req = Request(scope, receive, trust_proxy=["10.0.0.0/8", "192.168.1.0/24"]) # Client IP resolution ip = req.client_ip() Body Reading & Streaming Reading the body is idempotent and cached. If the body is read via await request.body(), subsequent calls return the cached bytes instantly. # Read full body (cached) body_bytes = await request.body() body_text = await request.text(encoding="utf-8") # Stream bytes in chunks async for chunk in request.iter_bytes(chunk_size=16384): await process_chunk(chunk) # Read exactly n bytes header = await request.readexactly(1024) Note: Calling iter_bytes() directly consumes the stream from ASGI. If you need to read the body both as a stream and as single-shot bytes, call await request.body() first to cache it. JSON & SURP Input Validation The json() and surp() methods parse the request body and support direct model validation: # Parse JSON as dict/list data = await request.json() # Parse and validate using a Pydantic model user = await request.json(model=UserCreateRequest) Auth, Session & DI Integration The Request coordinates with middleware to expose authenticated identity, active sessions, and dependency injection scopes: # Get active identity identity = request.identity is_auth = request.authenticated # Require auth (raises AUTH_REQUIRED structured fault if unauthenticated) user = request.require_identity() # Session integration session = request.session session["views"] = session.get("views", 0) + 1 # Dependency injection resolution db_service = await request.resolve(DatabaseService) Config Integrations Response )
Go to Homepage