Gestionnaires de route
Les gestionnaires de route (Route Handlers) vous permettent de créer des gestionnaires de requête personnalisés pour une route donnée en utilisant les API Web Request et Response.

Bon à savoir : Les gestionnaires de route sont uniquement disponibles dans le répertoire
app
. Ils sont l'équivalent des routes API dans le répertoirepages
, ce qui signifie que vous n'avez pas besoin d'utiliser à la fois les routes API et les gestionnaires de route.
Convention
Les gestionnaires de route sont définis dans un fichier route.js|ts
à l'intérieur du répertoire app
:
export async function GET(request: Request) {}
export async function GET(request) {}
Les gestionnaires de route peuvent être imbriqués n'importe où dans le répertoire app
, comme page.js
et layout.js
. Mais il ne peut pas y avoir de fichier route.js
au même niveau de segment de route que page.js
.
Méthodes HTTP supportées
Les méthodes HTTP suivantes sont supportées : GET
, POST
, PUT
, PATCH
, DELETE
, HEAD
et OPTIONS
. Si une méthode non supportée est appelée, Next.js renverra une réponse 405 Method Not Allowed
.
API étendues NextRequest
et NextResponse
En plus de supporter les API natives Request et Response, Next.js les étend avec NextRequest
et NextResponse
pour fournir des aides pratiques pour des cas d'utilisation avancés.
Comportement
Mise en cache
Les gestionnaires de route ne sont pas mis en cache par défaut. Vous pouvez cependant activer la mise en cache pour les méthodes GET
. Les autres méthodes HTTP supportées ne sont pas mises en cache. Pour mettre en cache une méthode GET
, utilisez une option de configuration de route comme export const dynamic = 'force-static'
dans votre fichier de gestionnaire de route.
export const dynamic = 'force-static'
export async function GET() {
const res = await fetch('https://data.mongodb-api.com/...', {
headers: {
'Content-Type': 'application/json',
'API-Key': process.env.DATA_API_KEY,
},
})
const data = await res.json()
return Response.json({ data })
}
export const dynamic = 'force-static'
export async function GET() {
const res = await fetch('https://data.mongodb-api.com/...', {
headers: {
'Content-Type': 'application/json',
'API-Key': process.env.DATA_API_KEY,
},
})
const data = await res.json()
return Response.json({ data })
}
Bon à savoir : Les autres méthodes HTTP supportées ne sont pas mises en cache, même si elles sont placées à côté d'une méthode
GET
qui est mise en cache, dans le même fichier.
Gestionnaires de route spéciaux
Les gestionnaires de route spéciaux comme sitemap.ts
, opengraph-image.tsx
, icon.tsx
et d'autres fichiers de métadonnées restent statiques par défaut, sauf s'ils utilisent des API dynamiques ou des options de configuration dynamiques.
Résolution de route
Vous pouvez considérer une route
comme la primitive de routage la plus basique.
- Elles ne participent pas aux layouts ou aux navigations côté client comme
page
. - Il ne peut pas y avoir de fichier
route.js
à la même route quepage.js
.
Page | Route | Résultat |
---|---|---|
app/page.js | app/route.js | Conflit |
app/page.js | app/api/route.js | Valide |
app/[user]/page.js | app/api/route.js | Valide |
Chaque fichier route.js
ou page.js
prend en charge tous les verbes HTTP pour cette route.
export default function Page() {
return <h1>Hello, Next.js!</h1>
}
// ❌ Conflit
// `app/route.ts`
export async function POST(request: Request) {}
export default function Page() {
return <h1>Hello, Next.js!</h1>
}
// ❌ Conflit
// `app/route.js`
export async function POST(request) {}
Exemples
Les exemples suivants montrent comment combiner les gestionnaires de route avec d'autres API et fonctionnalités de Next.js.
Révalidation des données en cache
Vous pouvez révalider les données en cache en utilisant la Régénération Statique Incrémentielle (ISR) :
export const revalidate = 60
export async function GET() {
const data = await fetch('https://api.vercel.app/blog')
const posts = await data.json()
return Response.json(posts)
}
export const revalidate = 60
export async function GET() {
const data = await fetch('https://api.vercel.app/blog')
const posts = await data.json()
return Response.json(posts)
}
Cookies
Vous pouvez lire ou définir des cookies avec cookies
de next/headers
. Cette fonction serveur peut être appelée directement dans un gestionnaire de route ou imbriquée dans une autre fonction.
Alternativement, vous pouvez renvoyer une nouvelle Response
en utilisant l'en-tête Set-Cookie
.
import { cookies } from 'next/headers'
export async function GET(request: Request) {
const cookieStore = await cookies()
const token = cookieStore.get('token')
return new Response('Hello, Next.js!', {
status: 200,
headers: { 'Set-Cookie': `token=${token.value}` },
})
}
import { cookies } from 'next/headers'
export async function GET(request) {
const cookieStore = await cookies()
const token = cookieStore.get('token')
return new Response('Hello, Next.js!', {
status: 200,
headers: { 'Set-Cookie': `token=${token}` },
})
}
Vous pouvez également utiliser les API Web sous-jacentes pour lire les cookies de la requête (NextRequest
) :
import { type NextRequest } from 'next/server'
export async function GET(request: NextRequest) {
const token = request.cookies.get('token')
}
export async function GET(request) {
const token = request.cookies.get('token')
}
En-têtes
Vous pouvez lire les en-têtes avec headers
de next/headers
. Cette fonction serveur peut être appelée directement dans un gestionnaire de route ou imbriquée dans une autre fonction.
Cette instance headers
est en lecture seule. Pour définir des en-têtes, vous devez renvoyer une nouvelle Response
avec de nouveaux headers
.
import { headers } from 'next/headers'
export async function GET(request: Request) {
const headersList = await headers()
const referer = headersList.get('referer')
return new Response('Hello, Next.js!', {
status: 200,
headers: { referer: referer },
})
}
import { headers } from 'next/headers'
export async function GET(request) {
const headersList = await headers()
const referer = headersList.get('referer')
return new Response('Hello, Next.js!', {
status: 200,
headers: { referer: referer },
})
}
Vous pouvez également utiliser les API Web sous-jacentes pour lire les en-têtes de la requête (NextRequest
) :
import { type NextRequest } from 'next/server'
export async function GET(request: NextRequest) {
const requestHeaders = new Headers(request.headers)
}
export async function GET(request) {
const requestHeaders = new Headers(request.headers)
}
Redirections
import { redirect } from 'next/navigation'
export async function GET(request: Request) {
redirect('https://nextjs.org/')
}
import { redirect } from 'next/navigation'
export async function GET(request) {
redirect('https://nextjs.org/')
}
Segments de route dynamiques
Les gestionnaires de route peuvent utiliser des segments dynamiques pour créer des gestionnaires de requête à partir de données dynamiques.
export async function GET(
request: Request,
{ params }: { params: Promise<{ slug: string }> }
) {
const { slug } = await params // 'a', 'b', ou 'c'
}
export async function GET(request, { params }) {
const { slug } = await params // 'a', 'b', ou 'c'
}
Route | URL exemple | params |
---|---|---|
app/items/[slug]/route.js | /items/a | Promise<{ slug: 'a' }> |
app/items/[slug]/route.js | /items/b | Promise<{ slug: 'b' }> |
app/items/[slug]/route.js | /items/c | Promise<{ slug: 'c' }> |
Paramètres de requête URL
L'objet requête passé au gestionnaire de route est une instance NextRequest
, qui inclut quelques méthodes pratiques supplémentaires, comme celles pour gérer plus facilement les paramètres de requête.
import { type NextRequest } from 'next/server'
export function GET(request: NextRequest) {
const searchParams = request.nextUrl.searchParams
const query = searchParams.get('query')
// query est "hello" pour /api/search?query=hello
}
export function GET(request) {
const searchParams = request.nextUrl.searchParams
const query = searchParams.get('query')
// query est "hello" pour /api/search?query=hello
}
Streaming
Le streaming est couramment utilisé en combinaison avec les modèles de langage de grande taille (LLM), comme OpenAI, pour du contenu généré par IA. En savoir plus sur le SDK IA.
import { openai } from '@ai-sdk/openai'
import { StreamingTextResponse, streamText } from 'ai'
export async function POST(req: Request) {
const { messages } = await req.json()
const result = await streamText({
model: openai('gpt-4-turbo'),
messages,
})
return new StreamingTextResponse(result.toAIStream())
}
import { openai } from '@ai-sdk/openai'
import { StreamingTextResponse, streamText } from 'ai'
export async function POST(req) {
const { messages } = await req.json()
const result = await streamText({
model: openai('gpt-4-turbo'),
messages,
})
return new StreamingTextResponse(result.toAIStream())
}
Ces abstractions utilisent les API Web pour créer un flux. Vous pouvez également utiliser directement les API Web sous-jacentes.
// https://developer.mozilla.org/docs/Web/API/ReadableStream#convert_async_iterator_to_stream
function iteratorToStream(iterator: any) {
return new ReadableStream({
async pull(controller) {
const { value, done } = await iterator.next()
if (done) {
controller.close()
} else {
controller.enqueue(value)
}
},
})
}
function sleep(time: number) {
return new Promise((resolve) => {
setTimeout(resolve, time)
})
}
const encoder = new TextEncoder()
async function* makeIterator() {
yield encoder.encode('<p>One</p>')
await sleep(200)
yield encoder.encode('<p>Two</p>')
await sleep(200)
yield encoder.encode('<p>Three</p>')
}
export async function GET() {
const iterator = makeIterator()
const stream = iteratorToStream(iterator)
return new Response(stream)
}
// https://developer.mozilla.org/docs/Web/API/ReadableStream#convert_async_iterator_to_stream
function iteratorToStream(iterator) {
return new ReadableStream({
async pull(controller) {
const { value, done } = await iterator.next()
if (done) {
controller.close()
} else {
controller.enqueue(value)
}
},
})
}
function sleep(time) {
return new Promise((resolve) => {
setTimeout(resolve, time)
})
}
const encoder = new TextEncoder()
async function* makeIterator() {
yield encoder.encode('<p>One</p>')
await sleep(200)
yield encoder.encode('<p>Two</p>')
await sleep(200)
yield encoder.encode('<p>Three</p>')
}
export async function GET() {
const iterator = makeIterator()
const stream = iteratorToStream(iterator)
return new Response(stream)
}
Corps de la requête
Vous pouvez lire le corps de la Request
en utilisant les méthodes standard des API Web :
export async function POST(request: Request) {
const res = await request.json()
return Response.json({ res })
}
export async function POST(request) {
const res = await request.json()
return Response.json({ res })
}
Corps de la requête FormData
Vous pouvez lire le FormData
en utilisant la fonction request.formData()
:
export async function POST(request: Request) {
const formData = await request.formData()
const name = formData.get('name')
const email = formData.get('email')
return Response.json({ name, email })
}
export async function POST(request) {
const formData = await request.formData()
const name = formData.get('name')
const email = formData.get('email')
return Response.json({ name, email })
}
Comme les données formData
sont toutes des chaînes de caractères, vous pouvez utiliser zod-form-data
pour valider la requête et récupérer les données dans le format que vous préférez (par exemple number
).
CORS
Vous pouvez définir les en-têtes CORS pour un gestionnaire de route spécifique en utilisant les méthodes standard des API Web :
export async function GET(request: Request) {
return new Response('Hello, Next.js!', {
status: 200,
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
},
})
}
export async function GET(request) {
return new Response('Hello, Next.js!', {
status: 200,
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
},
})
}
Bon à savoir :
- Pour ajouter des en-têtes CORS à plusieurs gestionnaires de route, vous pouvez utiliser un Middleware ou le fichier
next.config.js
.- Alternativement, consultez notre exemple CORS.
Webhooks
Vous pouvez utiliser un gestionnaire de route (Route Handler) pour recevoir des webhooks depuis des services tiers :
export async function POST(request: Request) {
try {
const text = await request.text()
// Process the webhook payload
} catch (error) {
return new Response(`Webhook error: ${error.message}`, {
status: 400,
})
}
return new Response('Success!', {
status: 200,
})
}
export async function POST(request) {
try {
const text = await request.text()
// Process the webhook payload
} catch (error) {
return new Response(`Webhook error: ${error.message}`, {
status: 400,
})
}
return new Response('Success!', {
status: 200,
})
}
Contrairement aux routes d'API avec le routeur Pages, vous n'avez pas besoin d'utiliser bodyParser
ni aucune configuration supplémentaire.
Réponses non-UI
Vous pouvez utiliser des gestionnaires de route pour retourner du contenu non-UI. Notez que sitemap.xml
, robots.txt
, icônes d'application
et images open graph ont tous un support intégré.
export async function GET() {
return new Response(
`<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
<title>Next.js Documentation</title>
<link>https://nextjs.org/docs</link>
<description>The React Framework for the Web</description>
</channel>
</rss>`,
{
headers: {
'Content-Type': 'text/xml',
},
}
)
}
export async function GET() {
return new Response(`<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
<title>Next.js Documentation</title>
<link>https://nextjs.org/docs</link>
<description>The React Framework for the Web</description>
</channel>
</rss>`)
}
Options de configuration des segments
Les gestionnaires de route utilisent la même configuration de segment de route que les pages et les layouts.
export const dynamic = 'auto'
export const dynamicParams = true
export const revalidate = false
export const fetchCache = 'auto'
export const runtime = 'nodejs'
export const preferredRegion = 'auto'
export const dynamic = 'auto'
export const dynamicParams = true
export const revalidate = false
export const fetchCache = 'auto'
export const runtime = 'nodejs'
export const preferredRegion = 'auto'
Consultez la référence API pour plus de détails.