description |
---|
Use Middleware to run code before a request is completed. |
Middleware is created by using a middleware
function that lives inside a _middleware
file. The Middleware API is based upon the native FetchEvent
, Response
, and Request
objects.
These native Web API objects are extended to give you more control over how you manipulate and configure a response, based on the incoming requests.
The function signature:
import type { NextFetchEvent } from 'next/server'
import type { NextRequest } from 'next/server'
export type Middleware = (
request: NextRequest,
event: NextFetchEvent
) => Promise<Response | undefined> | Response | undefined
The function can be a default export and as such, does not have to be named middleware
. Though this is a convention. Also note that you only need to make the function async
if you are running asynchronous code.
The NextFetchEvent
object extends the native FetchEvent
object, and includes the waitUntil()
method.
The waitUntil()
method can be used to prolong the execution of the function, after the response has been sent. In practice this means that you can send a response, then continue the function execution if you have other background work to make.
An example of why you would use waitUntil()
is integrations with logging tools such as Sentry or DataDog. After the response has been sent, you can send logs of response times, errors, API call durations or overall performance metrics.
The event
object is fully typed and can be imported from next/server
.
import { NextFetchEvent } from 'next/server'
The NextRequest
object is an extension of the native Request
interface, with the following added methods and properties:
cookies
- Has the cookies from theRequest
nextUrl
- Includes an extended, parsed, URL object that gives you access to Next.js specific properties such aspathname
,basePath
,trailingSlash
andi18n
geo
- Has the geo location from theRequest
geo.country
- The country codegeo.region
- The region codegeo.city
- The citygeo.latitude
- The latitudegeo.longitude
- The longitude
ip
- Has the IP address of theRequest
ua
- Has the user agent
You can use the NextRequest
object as a direct replacement for the native Request
interface, giving you more control over how you manipulate the request.
NextRequest
is fully typed and can be imported from next/server
.
import type { NextRequest } from 'next/server'
The NextResponse
object is an extension of the native Response
interface, with the following added methods and properties:
cookies
- An object with the cookies in theResponse
redirect()
- Returns aNextResponse
with a redirect setrewrite()
- Returns aNextResponse
with a rewrite setnext()
- Returns aNextResponse
that will continue the middleware chain
All methods above return a NextResponse
object that only takes effect if it's returned in the middleware function.
NextResponse
is fully typed and can be imported from next/server
.
import { NextResponse } from 'next/server'
When using redirect()
you may notice that the status codes used are 307
for a temporary redirect, and 308
for a permanent redirect. While traditionally a 302
was used for a temporary redirect, and a 301
for a permanent redirect, many browsers changed the request method of the redirect, from a POST
to GET
request when using a 302
, regardless of the origins request method.
Taking the following example of a redirect from /users
to /people
, if you make a POST
request to /users
to create a new user, and are conforming to a 302
temporary redirect, the request method will be changed from a POST
to a GET
request. This doesn't make sense, as to create a new user, you should be making a POST
request to /people
, and not a GET
request.
The introduction of the 307
status code means that the request method is preserved as POST
.
302
- Temporary redirect, will change the request method fromPOST
toGET
307
- Temporary redirect, will preserve the request method asPOST
The redirect()
method uses a 307
by default, instead of a 302
temporary redirect, meaning your requests will always be preserved as POST
requests.