Middleware
Middleware ermöglicht es Ihnen, Code auszuführen, bevor eine Anfrage abgeschlossen wird. Basierend auf der eingehenden Anfrage können Sie die Antwort durch Umschreiben, Weiterleiten, Ändern der Anfrage- oder Antwortheader oder durch direkte Antwort modifizieren.
Middleware wird ausgeführt, bevor zwischengespeicherte Inhalte und Routen abgeglichen werden. Weitere Details finden Sie unter Pfadabgleich.
Konvention
Verwenden Sie die Datei middleware.ts
(oder .js
) im Stammverzeichnis Ihres Projekts, um Middleware zu definieren. Zum Beispiel auf derselben Ebene wie pages
oder app
, oder innerhalb von src
, falls zutreffend.
Beispiel
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
// Diese Funktion kann als `async` markiert werden, wenn `await` intern verwendet wird
export function middleware(request: NextRequest) {
return NextResponse.redirect(new URL('/home', request.url))
}
// Siehe "Pfadabgleich" unten für weitere Informationen
export const config = {
matcher: '/about/:path*',
}
import { NextResponse } from 'next/server'
// Diese Funktion kann als `async` markiert werden, wenn `await` intern verwendet wird
export function middleware(request) {
return NextResponse.redirect(new URL('/home', request.url))
}
// Siehe "Pfadabgleich" unten für weitere Informationen
export const config = {
matcher: '/about/:path*',
}
Pfadabgleich
Middleware wird für jede Route in Ihrem Projekt aufgerufen. Die folgende Reihenfolge wird eingehalten:
headers
ausnext.config.js
redirects
ausnext.config.js
- Middleware (
rewrites
,redirects
, etc.) beforeFiles
(rewrites
) ausnext.config.js
- Dateisystemrouten (
public/
,_next/static/
,pages/
,app/
, etc.) afterFiles
(rewrites
) ausnext.config.js
- Dynamische Routen (
/blog/[slug]
) fallback
(rewrites
) ausnext.config.js
Es gibt zwei Möglichkeiten zu definieren, auf welchen Pfaden die Middleware ausgeführt wird:
Matcher
matcher
ermöglicht es Ihnen, Middleware auf bestimmte Pfade zu filtern.
export const config = {
matcher: '/about/:path*',
}
Sie können einen einzelnen Pfad oder mehrere Pfade mit einer Array-Syntax abgleichen:
export const config = {
matcher: ['/about/:path*', '/dashboard/:path*'],
}
Die matcher
-Konfiguration erlaubt volle Regex-Unterstützung, sodass Abgleiche wie negative Lookaheads oder Zeichenabgleiche möglich sind. Ein Beispiel für einen negativen Lookahead, um alle Pfade außer bestimmten abzugleichen, sieht folgendermaßen aus:
export const config = {
matcher: [
/*
* Alle Anfragepfade abgleichen, außer denen, die beginnen mit:
* - api (API-Routen)
* - _next/static (statische Dateien)
* - _next/image (Bildoptimierungsdateien)
* - favicon.ico (Favicon-Datei)
*/
'/((?!api|_next/static|_next/image|favicon.ico).*)',
],
}
Wichtig: Die
matcher
-Werte müssen Konstanten sein, damit sie zur Build-Zeit statisch analysiert werden können. Dynamische Werte wie Variablen werden ignoriert.
Konfigurierte Matcher:
- MÜSSEN mit
/
beginnen - Können benannte Parameter enthalten:
/about/:path
passt auf/about/a
und/about/b
, aber nicht auf/about/a/c
- Können Modifikatoren für benannte Parameter haben (beginnend mit
:
):/about/:path*
passt auf/about/a/b/c
, weil*
null oder mehr bedeutet.?
bedeutet null oder eins und+
eins oder mehr - Können reguläre Ausdrücke in Klammern verwenden:
/about/(.*)
ist dasselbe wie/about/:path*
Weitere Details finden Sie in der path-to-regexp-Dokumentation.
Wichtig: Aus Gründen der Abwärtskompatibilität betrachtet Next.js
/public
immer als/public/index
. Daher passt ein Matcher von/public/:path
darauf.
Bedingte Anweisungen
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
export function middleware(request: NextRequest) {
if (request.nextUrl.pathname.startsWith('/about')) {
return NextResponse.rewrite(new URL('/about-2', request.url))
}
if (request.nextUrl.pathname.startsWith('/dashboard')) {
return NextResponse.rewrite(new URL('/dashboard/user', request.url))
}
}
import { NextResponse } from 'next/server'
export function middleware(request) {
if (request.nextUrl.pathname.startsWith('/about')) {
return NextResponse.rewrite(new URL('/about-2', request.url))
}
if (request.nextUrl.pathname.startsWith('/dashboard')) {
return NextResponse.rewrite(new URL('/dashboard/user', request.url))
}
}
NextResponse
Die NextResponse
-API ermöglicht Ihnen:
- Die eingehende Anfrage auf eine andere URL
umzuleiten
- Die Antwort durch Anzeige einer bestimmten URL
umzuschreiben
- Anfrageheader für API-Routen,
getServerSideProps
undrewrite
-Ziele zu setzen - Antwort-Cookies zu setzen
- Antwortheader zu setzen
Um eine Antwort aus der Middleware zu erzeugen, können Sie:
- Auf eine Route (Page oder Edge API Route)
umschreiben
, die eine Antwort erzeugt - Direkt eine
NextResponse
zurückgeben. Siehe Antwort erzeugen
Cookies verwenden
Cookies sind reguläre Header. Bei einer Request
werden sie im Cookie
-Header gespeichert. Bei einer Response
befinden sie sich im Set-Cookie
-Header. Next.js bietet eine bequeme Möglichkeit, auf diese Cookies zuzugreifen und sie über die cookies
-Erweiterung von NextRequest
und NextResponse
zu manipulieren.
- Für eingehende Anfragen bietet
cookies
folgende Methoden:get
,getAll
,set
unddelete
Cookies. Sie können mithas
auf die Existenz eines Cookies prüfen oder mitclear
alle Cookies entfernen. - Für ausgehende Antworten bieten
cookies
folgende Methoden:get
,getAll
,set
unddelete
.
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
export function middleware(request: NextRequest) {
// Angenommen, ein "Cookie:nextjs=fast"-Header ist in der eingehenden Anfrage vorhanden
// Cookies aus der Anfrage mit der `RequestCookies`-API abrufen
let cookie = request.cookies.get('nextjs')
console.log(cookie) // => { name: 'nextjs', value: 'fast', Path: '/' }
const allCookies = request.cookies.getAll()
console.log(allCookies) // => [{ name: 'nextjs', value: 'fast' }]
request.cookies.has('nextjs') // => true
request.cookies.delete('nextjs')
request.cookies.has('nextjs') // => false
// Cookies in der Antwort mit der `ResponseCookies`-API setzen
const response = NextResponse.next()
response.cookies.set('vercel', 'fast')
response.cookies.set({
name: 'vercel',
value: 'fast',
path: '/',
})
cookie = response.cookies.get('vercel')
console.log(cookie) // => { name: 'vercel', value: 'fast', Path: '/' }
// Die ausgehende Antwort hat einen `Set-Cookie:vercel=fast;path=/test`-Header.
return response
}
import { NextResponse } from 'next/server'
export function middleware(request) {
// Angenommen, ein "Cookie:nextjs=fast"-Header ist in der eingehenden Anfrage vorhanden
// Cookies aus der Anfrage mit der `RequestCookies`-API abrufen
let cookie = request.cookies.get('nextjs')
console.log(cookie) // => { name: 'nextjs', value: 'fast', Path: '/' }
const allCookies = request.cookies.getAll()
console.log(allCookies) // => [{ name: 'nextjs', value: 'fast' }]
request.cookies.has('nextjs') // => true
request.cookies.delete('nextjs')
request.cookies.has('nextjs') // => false
// Cookies in der Antwort mit der `ResponseCookies`-API setzen
const response = NextResponse.next()
response.cookies.set('vercel', 'fast')
response.cookies.set({
name: 'vercel',
value: 'fast',
path: '/',
})
cookie = response.cookies.get('vercel')
console.log(cookie) // => { name: 'vercel', value: 'fast', Path: '/' }
// Die ausgehende Antwort hat einen `Set-Cookie:vercel=fast;path=/test`-Header.
return response
}
Header setzen
Sie können Anfrage- und Antwortheader mit der NextResponse
-API setzen (das Setzen von Anfrage-Headern ist seit Next.js v13.0.0 verfügbar).
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
export function middleware(request: NextRequest) {
// Die Anfrageheader klonen und einen neuen Header `x-hello-from-middleware1` setzen
const requestHeaders = new Headers(request.headers)
requestHeaders.set('x-hello-from-middleware1', 'hello')
// Sie können Anfrageheader auch in NextResponse.rewrite setzen
const response = NextResponse.next({
request: {
// Neue Anfrageheader
headers: requestHeaders,
},
})
// Einen neuen Antwortheader `x-hello-from-middleware2` setzen
response.headers.set('x-hello-from-middleware2', 'hello')
return response
}
import { NextResponse } from 'next/server'
export function middleware(request) {
// Die Anfrageheader klonen und einen neuen Header `x-hello-from-middleware1` setzen
const requestHeaders = new Headers(request.headers)
requestHeaders.set('x-hello-from-middleware1', 'hello')
// Sie können Anfrageheader auch in NextResponse.rewrite setzen
const response = NextResponse.next({
request: {
// Neue Anfrageheader
headers: requestHeaders,
},
})
// Einen neuen Antwortheader `x-hello-from-middleware2` setzen
response.headers.set('x-hello-from-middleware2', 'hello')
return response
}
Wichtig: Vermeiden Sie das Setzen großer Header, da dies je nach Konfiguration Ihres Backend-Webservers zu einem 431 Request Header Fields Too Large-Fehler führen kann.
Antwort erzeugen
Sie können direkt aus der Middleware antworten, indem Sie eine Response
- oder NextResponse
-Instanz zurückgeben. (Dies ist seit Next.js v13.1.0 verfügbar.)
import { NextRequest } from 'next/server'
import { isAuthenticated } from '@lib/auth'
// Die Middleware auf Pfade beschränken, die mit `/api/` beginnen
export const config = {
matcher: '/api/:function*',
}
export function middleware(request: NextRequest) {
// Unsere Authentifizierungsfunktion aufrufen, um die Anfrage zu prüfen
if (!isAuthenticated(request)) {
// Mit JSON antworten, das eine Fehlermeldung anzeigt
return Response.json(
{ success: false, message: 'Authentifizierung fehlgeschlagen' },
{ status: 401 }
)
}
}
import { isAuthenticated } from '@lib/auth'
// Die Middleware auf Pfade beschränken, die mit `/api/` beginnen
export const config = {
matcher: '/api/:function*',
}
export function middleware(request) {
// Unsere Authentifizierungsfunktion aufrufen, um die Anfrage zu prüfen
if (!isAuthenticated(request)) {
// Mit JSON antworten, das eine Fehlermeldung anzeigt
return Response.json(
{ success: false, message: 'Authentifizierung fehlgeschlagen' },
{ status: 401 }
)
}
}
Erweiterte Middleware-Flags
In v13.1
von Next.js wurden zwei zusätzliche Flags für Middleware eingeführt, skipMiddlewareUrlNormalize
und skipTrailingSlashRedirect
, um erweiterte Anwendungsfälle zu behandeln.
skipTrailingSlashRedirect
ermöglicht das Deaktivieren der standardmäßigen Next.js-Weiterleitungen für das Hinzufügen oder Entfernen von nachgestellten Schrägstrichen, wodurch eine benutzerdefinierte Behandlung innerhalb der Middleware ermöglicht wird. Dies kann das Beibehalten des nachgestellten Schrägstrichs für einige Pfade, aber nicht für andere erleichtern, was schrittweise Migrationen vereinfacht.
module.exports = {
skipTrailingSlashRedirect: true,
}
const legacyPrefixes = ['/docs', '/blog']
export default async function middleware(req) {
const { pathname } = req.nextUrl
if (legacyPrefixes.some((prefix) => pathname.startsWith(prefix))) {
return NextResponse.next()
}
// Behandlung nachgestellter Schrägstriche anwenden
if (
!pathname.endsWith('/') &&
!pathname.match(/((?!\.well-known(?:\/.*)?)(?:[^/]+\/)*[^/]+\.\w+)/)
) {
req.nextUrl.pathname += '/'
return NextResponse.redirect(req.nextUrl)
}
}
skipMiddlewareUrlNormalize
ermöglicht das Deaktivieren der URL-Normalisierung, die Next.js durchführt, um den Umgang mit direkten Besuchen und Client-Übergängen gleich zu machen. Es gibt einige erweiterte Fälle, in denen Sie die volle Kontrolle über die ursprüngliche URL benötigen, was dieses Flag ermöglicht.
module.exports = {
skipMiddlewareUrlNormalize: true,
}
export default async function middleware(req) {
const { pathname } = req.nextUrl
// GET /_next/data/build-id/hello.json
console.log(pathname)
// Mit dem Flag ist dies jetzt /_next/data/build-id/hello.json
// Ohne das Flag würde dies zu /hello normalisiert werden
}
Versionsverlauf
Version | Änderungen |
---|---|
v13.1.0 | Erweiterte Middleware-Flags hinzugefügt |
v13.0.0 | Middleware kann Anfrageheader, Antwortheader ändern und Antworten senden |
v12.2.0 | Middleware ist stabil, bitte siehe Upgrade-Leitfaden |
v12.0.9 | Absolute URLs in Edge Runtime erzwingen (PR) |
v12.0.0 | Middleware (Beta) hinzugefügt |