Every handler receives one object. Destructure the parts you need.
1const handler = async ({ state, matches, body, headers, request }) => {2 const id = matches.params.id; // route parameters3 const name = body?.name; // parsed request body4 const country = headers.get("CF-IPCountry");5 const method = request.method; // the raw Worker Request6 7 return res({ id, name, country, method });8};What each field holds
- state — the storage factory for this request. See State.
- matches — the route match: pathname, params and index.
- body — the parsed request body, already read for you.
- headers — the request headers.
- request — the untouched Cloudflare Worker Request, for anything else.
Body parsing
Apiker reads the body before your handler runs and picks the parser from the Content-Type header:
- application/json — parsed into an object, or null when the body is empty
- application/x-www-form-urlencoded and multipart/form-data — collected into a plain object of field names and values
- anything else, including no Content-Type — read as text
You can also call the parser yourself on a raw request:
import { readRequestBody } from "apiker";
const raw = await readRequestBody(request);Malformed JSON does not crash the Worker — the parse error is caught and returned as the response body, so a bad request is visible to the caller.
Query parameters
Query strings are not parsed for you. Read them from the request URL:
const { searchParams } = new URL(request.url);
const page = searchParams.get("page") || "1";Identifying the caller
Cloudflare puts the client IP in CF-Connecting-IP. Apiker wraps that with helpers you should prefer, because they never expose a raw address to storage:
import { getRawIp, getSignedIp, getClientId } from "apiker";
getRawIp(); // the client IP
getSignedIp(); // a signed hash of it — safe to use as a storage key
getClientId(); // a hash of IP + User-Agent, used to pin tokens to a device

