middleware.js

Middleware allows you to run code before a request is completed.

Located at the project root (not inside /app! or inside /src if you use it. ) , the middleware runs before cached content and routes are matched.

Use Cases

Integrating Middleware into your application can significantly enhance performance, security, and user experience. Middleware is particularly effective in the following scenarios:

Execution Order

Middleware will be invoked for every route. It's crucial to precisely set the targets. The following is the execution order:
  1. headers from next.config.js
  2. redirects from next.config.js
  3. Middleware
  4. beforeFiles (rewrites) from next.config.js
  5. Filesystem routes (public/, _next/static/, pages/, app/, etc.)
  6. afterFiles (rewrites) from next.config.js
  7. Dynamic Routes (/blog/[slug])
  8. fallback (rewrites) from next.config.js
The waitUntil() method extends the lifetime of the Middleware until a promise settles.
import { NextResponse } from 'next/server'
import type { NextFetchEvent, NextRequest } from 'next/server'
export function middleware(req: NextRequest, event: NextFetchEvent) {
  event.waitUntil(
    fetch('https://my-analytics-platform.com', {
      method: 'POST',
      body: JSON.stringify({ pathname: req.nextUrl.pathname }),
    });
  );
  return NextResponse.next();
}
You can redirect or rewrite the incoming request to a different URL.
You can set CORS headers in Middleware to allow cross-origin requests.
import { NextRequest, NextResponse } from 'next/server'
const allowedOrigins = ['https://acme.com', 'https://my-app.org']
const corsOptions = {
  'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
  'Access-Control-Allow-Headers': 'Content-Type, Authorization',
}
export function middleware(request: NextRequest) {
  const origin = request.headers.get('origin') ?? '';        // Check the origin from the request
  if (request.method === 'OPTIONS') {
    const preflightHeaders = {
      ...(isAllowedOrigin && { 'Access-Control-Allow-Origin': origin }),
      ...corsOptions,
    }
    return NextResponse.json({}, { headers: preflightHeaders })
  }
  const response = NextResponse.next();          // Handle simple requests
  if (allowedOrigins.includes(origin)) response.headers.set('Access-Control-Allow-Origin', origin)
  Object.entries(corsOptions).forEach(([key, value]) => {
    response.headers.set(key, value)
  })
  return response;
}
export const config = {
  matcher: '/api/:path*',
}

Refer to the section on Authorization for another important use case of theMiddleware. Notice how cookies can be set in the Middleware.

Two configuration flags, skipMiddlewareUrlNormalize and skipTrailingSlashRedirect, are associated with the middleware.