Skip to content

Updating the Headers

The following middleware demonstrate how to interact with or modify a Response.

NOTE

Contrary to some middleware patterns out there, universal middlewares do not use a next() function. Instead, a middleware can return a function that will take the response as its first parameter.

ts
// src/middlewares/headers.middleware.ts

import type { Get, UniversalMiddleware } from "@universal-middleware/core";

// This middleware will add a `X-Universal-Hello` header to all responses
const headersMiddleware = (() => (request, ctx) => {
  return (response) => {
    // `ctx.hello` exists if it has been set by another middleware
    response.headers.set("X-Universal-Hello", ctx.hello ?? "world");

    return response;
  };
  // Using `satisfies` to not lose return type
}) satisfies Get<[], UniversalMiddleware<{ hello?: string }>>;

// export default is mandatory
export default headersMiddleware;

After bundling and publishing this middleware, one can then use this middleware as follows:

ts
import handler from "@universal-middleware-examples/tool/dummy-handler-hono";
import contextMiddleware from "@universal-middleware-examples/tool/middlewares/context-middleware-hono";
import headersMiddleware from "@universal-middleware-examples/tool/middlewares/headers-middleware-hono";
import paramsHandler from "@universal-middleware-examples/tool/params-handler-hono";
import compress from "@universal-middleware/compress/hono";
import { Hono } from "hono";

const app = new Hono();

// Now the universal context contains `{ hello: "World!!!" }`.
// See /examples/context-middleware
app.use(contextMiddleware("World!!!"));

// After a Response has been returned by the handler below,
// the `{ "X-Universal-Hello": "World!!!" }` header is appended to it
app.use(headersMiddleware());

app.use(compress());

app.get("/user/:name", paramsHandler());

app.get("/", handler());

export default app;
ts
import handler from "@universal-middleware-examples/tool/dummy-handler-h3";
import contextMiddleware from "@universal-middleware-examples/tool/middlewares/context-middleware-h3";
import headersMiddleware from "@universal-middleware-examples/tool/middlewares/headers-middleware-h3";
import paramsHandler from "@universal-middleware-examples/tool/params-handler-h3";
import compress from "@universal-middleware/compress/h3";
import { universalOnBeforeResponse } from "@universal-middleware/h3";
import { createApp, createRouter, toNodeListener } from "h3";
import { args } from "./utils";

const app = createApp({
  // /!\ This is required for universal-middleware to operate properly
  onBeforeResponse: universalOnBeforeResponse,
});

// Now the universal context contains `{ hello: "World!!!" }`.
// See /examples/context-middleware
app.use(contextMiddleware("World!!!"));

// After a Response has been returned by the handler below,
// the `{ "X-Universal-Hello": "World!!!" }` header is appended to it
app.use(headersMiddleware());

app.use(compress());

const router = createRouter();

router.get("/user/:name", paramsHandler());

router.get("/", handler());

app.use(router);

const port = args.port ? Number.parseInt(args.port) : 3000;

const { createServer } = await import("node:http");
createServer(toNodeListener(app)).listen(port, "localhost", () => {
  console.log(`Server listening on http://localhost:${port}`);
});
ts
import { createServer } from "@hattip/adapter-node";
import { createRouter } from "@hattip/router";
import handler from "@universal-middleware-examples/tool/dummy-handler-hattip";
import contextMiddleware from "@universal-middleware-examples/tool/middlewares/context-middleware-hattip";
import headersMiddleware from "@universal-middleware-examples/tool/middlewares/headers-middleware-hattip";
import paramsHandler from "@universal-middleware-examples/tool/params-handler-hattip";
import compress from "@universal-middleware/compress/hattip";
import { args } from "./utils";

const app = createRouter();

// Now the universal context contains `{ hello: "World!!!" }`.
// See /examples/context-middleware
app.use(contextMiddleware("World!!!"));

// After a Response has been returned by the handler below,
// the `{ "X-Universal-Hello": "World!!!" }` header is appended to it
app.use(headersMiddleware());

app.use(compress());

app.get("/user/:name", paramsHandler());

app.get("/", handler());

const hattipHandler = app.buildHandler();

const port = args.port ? Number.parseInt(args.port) : 3000;

createServer(hattipHandler).listen(port, () => {
  console.log(`Server listening on http://localhost:${port}`);
});
ts
import handler from "@universal-middleware-examples/tool/dummy-handler";
import contextMiddleware from "@universal-middleware-examples/tool/middlewares/context-middleware";
import headersMiddleware from "@universal-middleware-examples/tool/middlewares/headers-middleware";
import paramsHandler from "@universal-middleware-examples/tool/params-handler";
import { createHandler } from "@universal-middleware/cloudflare";
import { pipe } from "@universal-middleware/core";

const paramsHandlerInstance = paramsHandler({
  route: "/user/:name",
});

// Cloudflare Workers have no internal way of representing a middleware
// Instead, we use the universal `pipe` operator
const wrapped = pipe(
  contextMiddleware("World!!!"),
  headersMiddleware(),
  (request, ctx, runtime) => {
    const url = new URL(request.url);
    if (url.pathname.startsWith("/user/")) {
      return paramsHandlerInstance(request, ctx, runtime);
    }
  },
  handler(),
);

export default createHandler(() => wrapped)();
ts
// functions/index.ts

import handler from "@universal-middleware-examples/tool/dummy-handler-cloudflare-pages";

export const onRequest = handler();

// functions/_middlewares.ts
// See https://developers.cloudflare.com/pages/functions/middleware/

import contextMiddleware from "@universal-middleware-examples/tool/middlewares/context-middleware-cloudflare-pages";
import headersMiddleware from "@universal-middleware-examples/tool/middlewares/headers-middleware-cloudflare-pages";

export const onRequest = [contextMiddleware("World!!!"), headersMiddleware()];
ts
import handler from "@universal-middleware-examples/tool/dummy-handler-express";
import contextMiddleware from "@universal-middleware-examples/tool/middlewares/context-middleware-express";
import headersMiddleware from "@universal-middleware-examples/tool/middlewares/headers-middleware-express";
import paramsHandler from "@universal-middleware-examples/tool/params-handler-express";
import compress from "@universal-middleware/compress/express";
import express from "express";
import { args } from "./utils";

const app = express();

// Now the universal context contains `{ hello: "World!!!" }`.
// See /examples/context-middleware
app.use(contextMiddleware("World!!!"));

// After a Response has been returned by the handler below,
// the `{ "X-Universal-Hello": "World!!!" }` header is appended to it
app.use(headersMiddleware());

app.use(compress());

app.get("/user/:name", paramsHandler());

app.get("/", handler());

const port = args.port ? Number.parseInt(args.port) : 3000;

app.listen(port, "localhost", () => {
  console.log(`Server listening on http://localhost:${port}`);
});
ts
import handler from "@universal-middleware-examples/tool/dummy-handler-fastify";
import contextMiddleware from "@universal-middleware-examples/tool/middlewares/context-middleware-fastify";
import headersMiddleware from "@universal-middleware-examples/tool/middlewares/headers-middleware-fastify";
import paramsHandler from "@universal-middleware-examples/tool/params-handler-fastify";
import compress from "@universal-middleware/compress/fastify";
import fastify from "fastify";
import rawBody from "fastify-raw-body";
import { args } from "./utils";

const app = fastify();

// /!\ Mandatory if you need to access the request body in any Universal Middleware or Handler
await app.register(rawBody);

// Now the universal context contains `{ hello: "World!!!" }`.
// See /examples/context-middleware
app.register(contextMiddleware("World!!!"));

// After a Response has been returned by the handler below,
// the `{ "X-Universal-Hello": "World!!!" }` header is appended to it
app.register(headersMiddleware());

app.register(compress());

app.get("/user/:name", paramsHandler());

app.get("/", handler());

const port = args.port ? Number.parseInt(args.port) : 3000;

app.listen(
  {
    port,
    host: "localhost",
  },
  () => {
    console.log(`Server listening on http://localhost:${port}`);
  },
);
ts
import handler from "@universal-middleware-examples/tool/dummy-handler-elysia";
import contextMiddleware from "@universal-middleware-examples/tool/middlewares/context-middleware-elysia";
import headersMiddleware from "@universal-middleware-examples/tool/middlewares/headers-middleware-elysia";
import paramsHandler from "@universal-middleware-examples/tool/params-handler-elysia";
import compress from "@universal-middleware/compress/elysia";
import Elysia from "elysia";
import { args } from "./utils";

const port = args.port ? Number.parseInt(args.port) : 3000;

new Elysia()
  .use(contextMiddleware("World!!!"))
  .use(headersMiddleware())
  .use(compress())
  .get("/user/:name", paramsHandler())
  .get("/", handler())
  .listen(port, () => {
    console.log(`Server listening on http://localhost:${port}`);
  });