Request API
primate/request exports the application-visible request type received by
route handlers, hooks, layouts, and request-aware module hooks.
import type { RequestFacade } from "primate/request";This entrypoint has no runtime default export. RequestBody, RequestBag, and
RequestView below describe types exposed through RequestFacade; they are
not independent exports from primate/request. See the
Requests guide for workflows and longer examples.
RequestFacade
type RequestFacade = {
method: Method;
body: RequestBody;
cookies: RequestBag;
headers: RequestBag;
original: Request;
path: RequestBag;
query: RequestBag;
target: string;
url: URL;
forward(to: string, headers?: Dict<string>): Promise<Response>;
has(key: string): boolean;
try<T>(key: string): T | undefined;
get<T>(key: string): T;
set<T>(
key: string,
value: T | ((prev: T | undefined) => T),
): RequestFacade;
delete(key: string): RequestFacade;
toJSON(): RequestView;
};Route schemas supplied through route.with() narrow
the body, path, and query properties before the handler runs.
request.method
The normalized lowercase HTTP method.
request.method: Method;See the supported Method union.
request.body
Content-type-aware access to the incoming body.
request.body: RequestBody;Use exactly one reader from RequestBody. With a body schema,
the reader matching the route's declared content type returns the schema's
awaited inferred type.
request.path
Decoded dynamic route parameters.
request.path: RequestBag;Path keys are normalized to lowercase. raw is the request pathname. A path
schema changes the bag's generic value type.
request.query
Query-string values.
request.query: RequestBag;Keys are case-insensitive and normalized to lowercase. Repeated keys keep the
last value; raw preserves the original search string, including its leading
?. A query schema changes the bag's generic value type.
request.headers
Request headers as a case-insensitive RequestBag.
request.headers: RequestBag;Header keys are lowercase. Values reflect the runtime's WHATWG Headers
normalization before the bag is created. The bag's raw string is empty; use
request.original.headers when the native Headers interface is required.
request.cookies
Cookies parsed from the Cookie header.
request.cookies: RequestBag;Cookie names and values are URL-decoded when possible. Names are
case-sensitive, a repeated name keeps its last value, and raw is the original
Cookie header or "".
request.original
The original platform WHATWG request.
request.original: Request;Use it for native operations such as clone(), formData(), direct stream
access, or the abort signal. Request-context values are not added to it.
request.target
The request target composed from pathname and query string.
request.target: string;For https://example.test/search?q=primate, the value is
"/search?q=primate".
request.url
The parsed absolute request URL.
request.url: URL;
request.forward()
Forwards the original request method and body to another URL.
forward(to: string, headers?: Dict<string>): Promise<Response>;tois passed tofetch.headerssupplies additional outgoing headers.- The original
Content-Typeis always forwarded and takes precedence over a same-cased value inheaders. - Other original headers, cookies, request context, and the original abort signal are not copied automatically.
Returns: The upstream native Response.
The body is the original request stream. Forward before consuming it through a body reader, and disable route body parsing when the route is only a proxy.
request.has()
Checks whether the request context contains a key.
has(key: string): boolean;This tests key presence, even when the stored value is undefined.
request.try()
Reads a typed request-context value without requiring it to exist.
try<T>(key: string): T | undefined;The generic is a caller assertion; context keys do not carry a shared runtime schema.
request.get()
Reads a required typed request-context value.
get<T>(key: string): T;Throws: Error("Missing context key: …") when the key is absent. A present
key whose value is undefined does not throw.
request.set()
Stores or updates a request-context value and returns the same facade for chaining.
set<T>(key: string, value: T): RequestFacade;
set<T>(
key: string,
update: (prev: T | undefined) => T,
): RequestFacade;The callback form receives the previous value or undefined. Context is
request-scoped, server-only, and may contain non-serializable values.
request.delete()
Removes a request-context key and returns the same facade.
delete(key: string): RequestFacade;Deleting a missing key has no effect.
request.toJSON()
Returns the client-safe request view used by rendering and hydration.
toJSON(): RequestView;Only normalized path, normalized query, and url are included. Body,
headers, cookies, context, method, target, and the original request are omitted.
RequestBody
The body-reader type exposed as request.body.
declare class RequestBody {
json(): Promise<JSONValue>;
form(): Promise<Record<string, string>>;
formEntries(): Promise<[string, string][]>;
multipart(): Promise<{
form: Record<string, string>;
files: Record<string, File>;
}>;
text(): Promise<string>;
blob(): Promise<Blob>;
}Every reader verifies the incoming media type and consumes the body once.
Calling a reader for a different content type or trying to parse the body again
throws. Media-type parameters such as a multipart boundary are ignored during
the comparison. Native decoding failures and schema parse failures reject the
returned promise; a Pema parse failure in a route handler becomes Primate's
400 JSON error response.
RequestBody.json()
json(): Promise<JSONValue>;Requires application/json. It uses the native Request.json() parser and,
when configured, returns the body schema's parsed value.
RequestBody.form()
form(): Promise<Record<string, string>>;Requires application/x-www-form-urlencoded. Repeated names keep their last
value. File entries are rejected because URL-encoded forms must contain text.
RequestBody.formEntries()
formEntries(): Promise<[string, string][]>;Requires application/x-www-form-urlencoded. Unlike form(), it preserves
repeated fields and submission order. This raw entry reader does not apply the
route body schema.
RequestBody.multipart()
multipart(): Promise<{
form: Record<string, string>;
files: Record<string, File>;
}>;Requires multipart/form-data. Text and file fields are separated by name;
repeated names keep the last value. A configured body schema parses the
combined { form, files } object.
RequestBody.text()
text(): Promise<string>;Requires text/plain and applies the configured body schema when present.
RequestBody.blob()
blob(): Promise<Blob>;Requires application/octet-stream and applies the configured body schema
when present.
RequestBag
Normalized key/value storage used for path, query, headers, and cookies.
declare class RequestBag<T extends Dict = Dict<string>>
implements Iterable<[keyof T & string, T[keyof T & string]]> {
get raw(): string;
get size(): number;
[Symbol.iterator](): IterableIterator<[
keyof T & string,
T[keyof T & string],
]>;
get<K extends keyof T & string>(key: K): T[K];
try<K extends keyof T & string>(key: K): T[K] | undefined;
has<K extends keyof T & string>(key: K): boolean;
toString(): string;
toJSON(): T;
}RequestBag instances also implement Pema's parseable protocol, so a Pema
object schema can parse a bag directly.
RequestBag.raw
The untouched source string associated with the bag.
get raw(): string;See each facade property above for its source value.
RequestBag.size
The number of normalized keys, including keys whose value is undefined.
get size(): number;
RequestBag[Symbol.iterator]()
Iterates normalized [key, value] pairs and skips entries whose value is
undefined.
[Symbol.iterator](): IterableIterator<[
keyof T & string,
T[keyof T & string],
]>;
RequestBag.get()
Returns a defined value after applying the bag's key normalization.
get<K extends keyof T & string>(key: K): T[K];Throws: When the normalized key is absent or its value is undefined.
RequestBag.try()
try<K extends keyof T & string>(key: K): T[K] | undefined;Returns undefined for an absent key or a key whose value is undefined.
RequestBag.has()
has<K extends keyof T & string>(key: K): boolean;Returns true only when the normalized key exists with a defined value.
RequestBag.toString()
Returns raw, which also makes template interpolation use
the original source string.
toString(): string;
RequestBag.toJSON()
Returns a shallow null-prototype clone of the normalized contents.
toJSON(): T;
RequestView
The value returned by request.toJSON().
type RequestView = {
path: PartialDict<string>;
query: PartialDict<string>;
url: URL;
};