Middleware

Middleware is the main composition mechanism in sevo.

Shape

Middleware receives (ctx, next) and can:

  • return a Response immediately
  • call next(ctx) and return the downstream response
  • replace the request before passing it on
import type { ServerMiddleware } from "sevo";

const poweredBy: ServerMiddleware = async (ctx, next) => {
  const response = await next(ctx);
  response.headers.set("x-powered-by", "sevo");
  return response;
};

Registering Middleware

import { serve } from "sevo";
import { NodeRuntimeAdapter } from "sevo/node";

serve({
  adapter: new NodeRuntimeAdapter(),
  middleware: [poweredBy],
  routes: {
    "/": () => new Response("ok"),
  },
  fetch: () => new Response("Not Found", { status: 404 }),
});

Short-Circuiting

Middleware can stop the chain by returning a response directly.

const auth: ServerMiddleware = async (ctx, next) => {
  if (!ctx.request.headers.get("authorization")) {
    return new Response("Unauthorized", { status: 401 });
  }
  return next(ctx);
};

Static Files

serveStatic() is implemented as middleware.

import { serve } from "sevo";
import { serveStatic } from "sevo/static";
import { NodeRuntimeAdapter } from "sevo/node";

serve({
  adapter: new NodeRuntimeAdapter(),
  middleware: [serveStatic({ dir: "./public" })],
  fetch: () => new Response("Not Found", { status: 404 }),
});

Request Logging

The optional logger lives in a separate subpath export.

import { serve } from "sevo";
import { log } from "sevo/log";
import { NodeRuntimeAdapter } from "sevo/node";

serve({
  adapter: new NodeRuntimeAdapter(),
  middleware: [log()],
  routes: {
    "/": () => new Response("ok"),
  },
  fetch: () => new Response("Not Found", { status: 404 }),
});

Plugins

ServerPlugin runs during Server construction and can modify server.options or register process-level behavior.

sevo itself uses plugins internally for:

  • request error normalization
  • graceful shutdown handling in supported runtimes