javascript / expert
Snippet
Implementing an Extensible Middleware Pipe with Functional Composition
As Next.js middleware grows, managing multiple logic blocks becomes difficult. Using functional composition (piping) allows you to wrap middleware functions like an onion, ensuring a clean separation of concerns for logging, auth, and headers.
snippet.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import { NextRequest, NextResponse } from 'next/server';type Middleware = (next: Function) => (req: NextRequest) => Promise<NextResponse>;const withCustomHeader: Middleware = (next) => async (req) => {const res = await next(req);res.headers.set('x-framework', 'nextjs-expert');return res;};const pipe = (...middlewares: Middleware[]) => (final: Function) =>middlewares.reduceRight((acc, m) => m(acc), final);export default pipe(withCustomHeader)(async (req: NextRequest) => NextResponse.next());
nextjs
Breakdown
1
reduceRight((acc, m) => m(acc), final)
Applying middlewares in reverse order to create a layered execution stack (onion pattern).
2
type Middleware = (next: Function) => ...
Defining a higher-order function type that wraps the next execution step in the chain.