CORE CONCEPTS
Request Utilities
ctx.request (and its alias ctx.req) is a standard Web API Request. Futon ships a small set of standalone helper functions for the common things you'd otherwise write by hand — URL parsing and body parsing.
URL Helpers
import { getPathname, getQueryParams, getQueryParam } from '@rasenganjs/futon'; app.get('/debug', async (ctx) => { const pathname = getPathname(ctx.request); // "/debug" const allParams = getQueryParams(ctx.request); // { page: "2", ... } const page = getQueryParam(ctx.request, 'page'); // "2" | null return json({ pathname, allParams, page }); });
Inside a handler, ctx.query (see Query
Parameters) is lazily parsed and cached —
prefer it over getQueryParams() unless you're working outside the request
lifecycle.
Body Parsing
The Request body is a ReadableStream — it can only be read once. Futon's body parsers are plain async functions you call directly, or via the bodyParser() middleware for automatic parsing.
import { parseJson, parseUrlEncoded, parseFormData, parseText, parseBody, } from '@rasenganjs/futon'; app.post('/api/data', async (ctx) => { const data = await parseJson(ctx.request); return json({ received: data }); });
parseBody() inspects the Content-Type header and dispatches to the right parser — this is exactly what the bodyParser() middleware uses internally.
Because the body stream can only be consumed once, call a parser exactly once per request — ideally in a middleware near the top of your chain, before any handler tries to read the body itself.
Multipart Form Data
For file uploads specifically, reach for fileUpload() instead of calling parseFormData() yourself — it handles field/file separation, size limits, and storage engines.
