Middleware
keiro
also supports a middleware.ts
file which is called before each route, to define a middleware:
import { defineMiddleware } from "keiro";
export default defineMiddleware((event, next) => { return next(event);});
API Reference
Middlewares take 2 arguments:
- RequestEvent: Contains the
request
,url
,params
,cookies
and requestlocals
. - Next: which represent the next handler in the chain.
And must return a Response object.
Middlewares can be defined in any of these ways:
-
Declaring a function.
import type { RequestEvent, Next } from "keiro/types";export default function middleware(event: RequestEvent, next: Next) {return next(event);} -
Using the
defineMiddleware
helper.import { defineMiddleware } from "keiro";export default defineMiddleware((event, next) => {return next(event);}) -
Using the
Middleware
type.import type { Middleware } from "keiro/types";export default ((event, next) => {return next(event);}) satisfies Middleware;
Chaining multiple middlewares
You can use multiple middlewares in a row using the sequence
helper.
import { sequence } from "keiro";
export default sequence(errorHandler(), logging(), auth())
Examples
Logging middleware
import { defineMiddleware } from "keiro";
export const logging = defineMiddleware(async (event, next) => { const request = event.request; const now = new Date();
// Get the response const response = await next(event);
const elapsed = Date.now() - now.getTime(); const duration = `${elapsed.toFixed(2)}ms`; const method = request.method; const path = event.url.pathname; const isOk = response.ok ? "✅" : "❌"; console.log(`${isOk} [${now.toISOString()}] ${method} ${path} ${duration}`);})
Error Handler middleware
import { defineMiddleware } from "keiro";
export const errorHandler = defineMiddleware(async (event, next) => { try { const response = await next(event); return response; } catch (err) { console.error(err); return Response.json( { error: "Internal error"}, { status: 500 } ) }})
Timeout middleware
import type { Middleware } from "keiro/types";
const delay = (ms: number) => new Promise<void>((r) => setTimeout(r, ms));
class TimeoutError extends Error {}
export const timeout = (ms: number): Middleware => { return async (event, next) => { try { const responsePromise = next(event); const errorPromise = delay(ms).then(() => Promise.reject(new TimeoutError())); const response = await Promise.race([responsePromise, errorPromise]); return response; } catch (err) { if (err instanceof TimeoutError) { return Response.json({ error: "Timeout" }, { status: 408 }); }
throw err; } };};
Auth middleware
import { defineMiddleware } from "keiro";import { getSession } from "@/lib/auth";
export const auth = defineMiddleware(async (event, next) => { const session = await getSession(event.cookies);
if (!session) { return new Response(null, { status: 401 }); }
return next(event);})