Middleware
Middleware Context Methods
Section titled “Middleware Context Methods”MiddlewareContext extends route context and adds:
.next(data?, request?): run downstream and returnPromise<Response>or throw.tryNext(data?, request?): run downstream and returnPromise<Result<Response, unknown>>.forward(data?, request?): run downstream and auto-callctx.resp(...).tryForward(data?, request?): like forward, but returnsResult
Be Nice Rules
Section titled “Be Nice Rules”- Do not drop the chain.
- Do not hoard errors.
Dropping the chain means middleware exits without calling .next()/.forward() and without sending a response.
Hoarding errors means catching errors but not rethrowing when they are not actually handled.
Pass Data Forward
Section titled “Pass Data Forward”import { middleware } from "@bronti/wooter"
const withRequestId = middleware<{ requestId: string }>(async (ctx) => { await ctx.forward({ requestId: crypto.randomUUID() })})Downstream handlers receive ctx.data.requestId with proper typing.
Result-Based Control
Section titled “Result-Based Control”const guard = middleware(async (ctx) => { const result = await ctx.tryNext({}) result.inspectErr((e) => { console.error("downstream failed", e) }) ctx.resp(result.match((r) => r, () => new Response("failed", { status: 500 })))})Use try* variants when middleware wants to inspect and branch on downstream failures.
Safe Exit Pattern
Section titled “Safe Exit Pattern”import { makeError, middleware } from "@bronti/wooter"
const json = middleware<{ json: () => Promise<unknown> }>(async ({ request, resp, forward, safeExit }) => { let parsed: unknown await forward({ json: async () => { if (parsed !== undefined) return parsed try { parsed = await request.clone().json() return parsed } catch { resp(makeError(400, "Invalid JSON")) safeExit() } }, })})This keeps parsing logic centralized and avoids repetitive handler-level try/catch.