Aura Router

Middlewares

Middlewares wrap around route handlers to implement cross‑cutting behaviors such as authentication, logging, CORS, and request/response shaping. There are two types:


Overview


Key Concepts

  • Middlewares enable the verification, enrichment, or modification of the request/response surrounding the handler.
  • Endpoint middlewares run with full type inference for params, searchParams, and body.
  • Global middlewares apply to all requests handled by a router and operate on the original Request.

Type Inference

Endpoint middlewares are type‑safe based on the endpoint’s Zod schemas for params, searchParams, and body. These types are inferred automatically from the endpoint configuration.

Global middlewares do not receive the typed context; they operate on the original Request.


Middlewares

Endpoint Middlewares

Endpoint middlewares are attached declaratively using createEndpointConfig. This approach ensures schema-based type safety.

Basic Usage

The following example demonstrates basic middleware usage without relying on the request context.

import { createEndpointConfig, createEndpoint } from "@aura-stack/router"

const config = createEndpointConfig({
  use: [
    async (ctx) => {
      console.log(`Request to ${ctx.url}`)
      return ctx
    },
  ],
})

const handler = async () => Response.json({})
const endpoint = createEndpoint("GET", "/protected", handler, config)

Context Usage

Context usage offers type inference powered by Zod Schemas, enabling type-safe validation and value mapping. The example below shows an endpoint middleware utilizing the request context.

import { z } from "zod"
import { createEndpoint, createEndpointConfig } from "@aura-stack/router"

const verifyToken = (token: string) => {
  /* Add logic */
  return token
}

const authConfig = createEndpointConfig({
  use: [
    async (ctx) => {
      const token = ctx.request.headers.get("authorization")

      if (!token || !token.startsWith("Bearer ")) {
        throw new Error("Unauthorized")
      }

      /*
       Verify token (simplified)
      */
      const userId = verifyToken(token.slice(7))

      /*
        Add user info to context
      */
      ctx.headers.setHeader("x-user-id", userId)
      return ctx
    },
  ],
})

const getProfile = createEndpoint(
  "GET",
  "/profile",
  async (ctx) => {
    const userId = ctx.headers.getHeader("x-user-id")
    return Response.json({ userId, name: "John" })
  },
  authConfig
)

Global Middlewares

Global middlewares are applied to all endpoints within a router via the createRouter configuration.

Middleware Chaining

Multiple middlewares execute in the order they are defined.

const config = createEndpointConfig({
  use: [
    /*
     1. First middleware - logging
    */
    async (ctx) => {
      console.log("1. Logging request")
      return ctx
    },
    /*
      2. Second middleware - auth
    */
    async (ctx) => {
      console.log("2. Checking auth")
      const token = ctx.request.headers.get("authorization")
      if (!token) throw new Error("Unauthorized")
      return ctx
    },
    /*
     3. Third middleware - add metadata
    */
    async (ctx) => {
      console.log("3. Adding metadata")
      ctx.headers.setHeader("x-processed", "true")
      return ctx
    },
  ],
})

Execution Order

When both global and endpoint middlewares are defined, they execute in the following sequence:

  1. Global middlewares (from createRouter)
  2. Endpoint middlewares (from createEndpointConfig)
  3. Route handler

Example

import { createEndpoint, createEndpointConfig, createRouter } from "@aura-stack/router"

const endpointConfig = createEndpointConfig({
  use: [
    async (ctx) => {
      console.log("2. Endpoint middleware")
      return ctx
    },
  ],
})

const endpoint = createEndpoint(
  "GET",
  "/test",
  async (ctx) => {
    console.log("3. Handler")
    return Response.json({ ok: true })
  },
  endpointConfig
)

const router = createRouter([endpoint], {
  use: [
    async (ctx) => {
      console.log("1. Global middleware")
      return ctx
    },
  ],
})

On this page