typescriptadvanced
Middleware Chain Pattern
Compose multiple middleware functions for auth, rate limiting, and geolocation in Next.js middleware.
typescriptPress ⌘/Ctrl + Shift + C to copy
// middleware.ts
import { NextRequest, NextResponse } from 'next/server';
type MiddlewareFn = (
req: NextRequest,
res: NextResponse,
) => NextResponse | Promise<NextResponse>;
// Compose middleware functions
function chain(...middlewares: MiddlewareFn[]) {
return async (req: NextRequest): Promise<NextResponse> => {
let response = NextResponse.next();
for (const mw of middlewares) {
response = await mw(req, response);
// If middleware redirected or returned error, stop chain
if (response.status >= 300) return response;
}
return response;
};
}
// Auth middleware
const withAuth: MiddlewareFn = (req, res) => {
const token = req.cookies.get('session')?.value;
const isProtected = req.nextUrl.pathname.startsWith('/dashboard');
if (isProtected && !token) {
const loginUrl = new URL('/login', req.url);
loginUrl.searchParams.set('redirect', req.nextUrl.pathname);
return NextResponse.redirect(loginUrl);
}
if (token) res.headers.set('x-user-authenticated', 'true');
return res;
};
// Rate limiting (simple in-memory)
const ipCounts = new Map<string, { count: number; reset: number }>();
const withRateLimit: MiddlewareFn = (req, res) => {
if (!req.nextUrl.pathname.startsWith('/api')) return res;
const ip = req.headers.get('x-forwarded-for') ?? 'unknown';
const now = Date.now();
const entry = ipCounts.get(ip);
if (!entry || now > entry.reset) {
ipCounts.set(ip, { count: 1, reset: now + 60000 });
} else {
entry.count++;
if (entry.count > 60) {
return new NextResponse('Too Many Requests', {
status: 429,
headers: { 'Retry-After': '60' },
});
}
}
return res;
};
// Security headers
const withSecurityHeaders: MiddlewareFn = (req, res) => {
res.headers.set('X-Frame-Options', 'DENY');
res.headers.set('X-Content-Type-Options', 'nosniff');
res.headers.set('Referrer-Policy', 'strict-origin-when-cross-origin');
return res;
};
// Compose and export
export const middleware = chain(
withSecurityHeaders,
withRateLimit,
withAuth,
);
export const config = {
matcher: ['/((?!_next/static|_next/image|favicon.ico).*)'],
};Sponsored
Vercel
Use Cases
- Auth guard middleware
- API rate limiting
- Security header injection
Tags
Related Snippets
Similar patterns you can reuse in the same workflow.
typescriptadvanced
Next.js Middleware for Authentication
Protect routes with Next.js middleware using token verification and role-based redirects.
Best for: Protecting authenticated routes at the edge
#nextjs#middleware
typescriptadvanced
Authentication Middleware with Session Check
Protect routes with middleware that validates session tokens and redirects unauthenticated users.
Best for: route protection
#nextjs#auth
typescriptintermediate
Authentication Middleware Guard
Next.js middleware that checks auth tokens on protected routes and redirects unauthenticated users to login.
Best for: Dashboard access control
#middleware#authentication
typescriptbeginner
Protected Page with Server Redirect
Server Component that checks auth status and redirects unauthenticated users before rendering any content.
Best for: Dashboard pages
#auth#redirect