Core Primitives β
bunway decorates Bunβs Fetch primitives with lightweight helpers. Understanding these building blocks makes it easier to compose middleware and handlers.
WayContext β
Every handler receives a WayContext
object:
app.use(async (ctx, next) => {
console.log(ctx.req.method, ctx.req.path);
await next();
});
ctx.req
β {@link WayRequest}: wrapper around BunβsRequest
withparams
,query
,locals
, body parsing helpers, etc.ctx.res
β {@link WayResponse}: fluent builder for returning JSON/text/any payloads while still exposing the underlyingResponse
.
WayRequest β
app.get("/users/:id", async (ctx) => {
const id = ctx.req.param("id");
const search = ctx.req.query.get("status");
const payload = await ctx.req.parseBody();
// Store data for downstream middleware/handlers
ctx.req.locals.user = { id, search, payload };
return ctx.res.ok({ id, search, payload });
});
Key helpers β
params
/param()
β Express-style route parameters.query
βURLSearchParams
instance for query string access.locals
β shared mutable state across middleware.body
β cached payload filled by the auto parser; perfect when you just need the data.parseBody()
β respects global + per-request overrides and returns the cached payload.applyBodyParserOverrides()
β tweak body parsing on the fly.rawBody()
/rawText()
β lazy access to the request body (cached).
Locals
Use ctx.req.locals
as a per-request scratchpad. Itβs perfect for sharing deserialized users, permissions, or tracing IDs between middleware and handlers.
Fun fact β The Bun way
ctx.req.bodyParseError
stores details when parsing fails (status + message). Check it before running expensive logic to send friendlier responses.
WayResponse β
app.post("/sessions", async (ctx) => {
const session = await createSession(ctx.req);
return ctx.res
.status(201)
.header("Set-Cookie", `session=${session.id}; HttpOnly; Path=/`)
.json({ id: session.id });
});
Key helpers β
status(code)
β chainable status setter.header(name, value)
β set response headers.json(data)
/text(string)
/send(body)
β return nativeResponse
objects.ok()
,created()
,noContent()
β handy sugar for common status codes.last
β inspect the last generatedResponse
object (router uses this fallback).
Response builders
WayResponse always returns native Fetch Response
objects, so you can pass them directly to Bun APIs or other tooling without serialization tricks.
Returning native Responses β
Prefer the Fetch API? Return a Response
directly and bunwayβs router will still merge middleware headers:
app.get("/raw", () => new Response("raw"));
Next steps β
With the primitives in mind, learn how routing works in bunway by reading the Router guide, then explore the built-in Middleware.