Volt v0.1 · TypeScript APIs on Bun · Get started
Docs/Core Concepts/Middleware Pipeline

Middleware Pipeline

Register middleware in the correct order and return its response.

Registration and execution

Register app.use() before the routes it should affect. Volt captures middleware when routes are registered. A middleware receives (context, next); return next(), or await it and return the resulting Response. Return an HTTP response early to stop the chain.

Complete global and route example

index.ts
import { Volt, type MiddlewareHandler } from 'voltts';

const timing: MiddlewareHandler = async (_c, next) => {
  const start = performance.now();
  const response = await next();
  if (response instanceof Response) {
    response.headers.set('Server-Timing', `app;dur=${performance.now() - start}`);
  }
  return response;
};
const requireKey: MiddlewareHandler = (c, next) => {
  if (c.headers.get('x-demo-key') !== 'tutorial-key') {
    return c.json({ error: 'Missing demo key' }, 401);
  }
  return next();
};
const app = new Volt();
// Register global middleware BEFORE registering routes.
app.use(timing);
app.get('/public', () => ({ public: true }));
// Arguments: path, handler, schema, route middleware array.
app.get('/private', () => ({ private: true }), undefined, [requireKey]);
if (globalThis._importMeta_.main) app.listen(3000);
export default app;

Try both branches

bash
bun run index.ts
curl -i http://localhost:3000/public
curl -i http://localhost:3000/private
curl -i http://localhost:3000/private -H 'x-demo-key: tutorial-key'

Expect 200, 401, and 200. Server-Timing is added to returned responses. The key is a tutorial value, not an authentication system.

Group middleware

Use group.use() before group routes, or pass middleware as the fourth argument to an individual route. Do not mix the handler and schema argument order: the signature is (path, handler, schema?, middleware[]?). See Route Groups.