context, and the incoming HTTP request lives on context.request. It is an HttpRequest instance (implementing the IRequest interface) that wraps the native Request and exposes the parsed pieces you actually need: the URL, the method, the headers, the query string, the route params, the decoded body, the client IP, the detected locale, and any uploaded files. The framework builds it from the native request before the controller runs, so you never construct one by hand. You read it.
For the values you reach for most, the context also carries convenience accessors that point straight at the request: context.params, context.queries, and context.payload are the same objects as context.request.params, context.request.queries, and context.request.payload.
What the request object holds
The nativeRequest gives you a raw URL string and a Headers bag. IRequest hands you a parsed IUrl, a typed queries record, route params, and the decoded payload, so you don’t re-parse in every controller. The interface is generic over params, payload, and queries, so a controller declares the exact shape it expects through IRequest<Config> and reads it with full typing.
The headers come decoded too: request.header is a Header object with helpers for content type, auth, cookies, and IP, plus a parsed userAgent. The request resolves a lang from the query string, a custom header, or Accept-Language, so locale is ready for translation without extra work. Multipart uploads are parsed into IRequestFile instances on request.files, each one exposing size, type, format detection, read methods, and a write to disk.
How it works
The framework reads the nativeRequest, extracts route params from the matched route and the decoded body, then constructs the HttpRequest. During construction it parses the URL (path, host, queries), normalizes the method, wraps the headers, parses the user agent, builds a RequestFile for every uploaded file, and resolves the locale.
Properties and methods
context.request exposes these read-only members:
Reading query and route params
Route params come from the dynamic segments of the matched route (/users/:id). Query params come from the URL query string (?page=2&search=alice). Read them from the request, or from the context.params / context.queries shortcuts.
Reading the payload
ForPOST, PUT, and PATCH requests the decoded body is on payload (and mirrored on context.payload). For JSON requests it is the parsed object; for form submissions it is the field record.
Headers and user agent
request.header is a Header object. Use get(name) and has(name) for raw values, or the typed convenience getters for common headers.
IUserAgent with browser, engine, os, device, and cpu. It is null when no User-Agent header is present.
File uploads
When the request is multipart form data, the framework parses it intorequest.form (the raw FormData) and request.files, a record keyed by form field name where each value is an IRequestFile. A RequestFile wraps the native File and adds metadata, format detection, read methods, and disk writing.
RequestFile API
Language and locale detection
Every request resolves alang ({ code, region }) during construction, with a fixed precedence:
When the locale comes from a query param or the custom header,
region is null and only code is set. When it falls back to Accept-Language, the first language is parsed into code and region (e.g. { code: "en", region: "US" }). If nothing matches, it defaults to en-US.
Reading the request well
For everyday access, readcontext.params, context.queries, and context.payload; reach for context.request when you need headers, IP, files, or locale. Declare a Config for IRequest<Config> (or cast) so those members are checked rather than typed any. Query and body values are user input, so run them through Validation before acting on them.
Treat the request as read-only. Every member of IRequest is immutable, so build your reply on context.response instead of changing the request. When you save an upload, use file.name, the generated collision-safe name, not the user-supplied originalName, and check size and the is* flags first. For locale, read request.lang rather than re-parsing Accept-Language yourself; it already applies the documented precedence.
Related
- Controllers: where the request reaches your handler via
context. - Validation: validate
params,queries, andpayloadbefore use. - Response: build the reply with
context.response. - Storage: persist uploaded files beyond a single request.