API Routes (Route Handlers)¶
Qu'est-ce qu'une Route API¶
Les Route Handlers de Next.js permettent de créer des points d'accès API directement dans votre application. Pas besoin d'un serveur backend séparé.
Les routes API sont définies dans des fichiers route.ts à l'intérieur du dossier app/api/.
app/
└── api/
└── produits/
├── route.ts → /api/produits (GET, POST)
└── [id]/
└── route.ts → /api/produits/1 (GET, PUT, DELETE)
Méthodes HTTP¶
Chaque fichier route.ts peut exporter des fonctions nommées selon la méthode HTTP : GET, POST, PUT, DELETE, etc.
GET et POST¶
import { prisma } from "@/lib/prisma";
import { NextResponse } from "next/server";
// GET /api/produits - Obtenir tous les produits
export async function GET() {
const produits = await prisma.produit.findMany({
include: { categorie: true },
});
return NextResponse.json(produits);
}
// POST /api/produits - Créer un produit
export async function POST(request: Request) {
const body = await request.json();
// Validation des données
if (!body.nom || !body.prix || !body.categorieId) {
return NextResponse.json(
{ erreur: "Les champs nom, prix et categorieId sont requis." },
{ status: 400 }
);
}
const produit = await prisma.produit.create({
data: {
nom: body.nom,
description: body.description,
prix: body.prix,
categorieId: body.categorieId,
},
});
return NextResponse.json(produit, { status: 201 });
}
GET, PUT et DELETE avec paramètre dynamique¶
import { prisma } from "@/lib/prisma";
import { NextResponse } from "next/server";
interface RouteParams {
params: Promise<{ id: string }>;
}
// GET /api/produits/:id - Obtenir un produit par son ID
export async function GET(request: Request, { params }: RouteParams) {
const { id } = await params;
const produit = await prisma.produit.findUnique({
where: { id: Number(id) },
include: { categorie: true },
});
if (!produit) {
return NextResponse.json(
{ erreur: "Produit non trouvé" },
{ status: 404 }
);
}
return NextResponse.json(produit);
}
// PUT /api/produits/:id - Modifier un produit
export async function PUT(request: Request, { params }: RouteParams) {
const { id } = await params;
const body = await request.json();
const produit = await prisma.produit.update({
where: { id: Number(id) },
data: {
nom: body.nom,
description: body.description,
prix: body.prix,
categorieId: body.categorieId,
},
});
return NextResponse.json(produit);
}
// DELETE /api/produits/:id - Supprimer un produit
export async function DELETE(request: Request, { params }: RouteParams) {
const { id } = await params;
await prisma.produit.delete({
where: { id: Number(id) },
});
return NextResponse.json({ message: "Produit supprimé" });
}
Tester les routes API¶
Vous pouvez tester vos routes API avec un outil comme Thunder Client (extension VS Code) ou directement dans le navigateur pour les requêtes GET.
Exemple de requête GET¶
Exemple de requête POST¶
curl -X POST http://localhost:3000/api/produits \
-H "Content-Type: application/json" \
-d '{"nom": "Casque audio", "prix": 199.99, "categorieId": 1}'
Validation des données¶
Il est important de valider les données reçues avant de les traiter. Dans l'exemple ci-dessus, nous vérifions que les champs obligatoires sont présents :
if (!body.nom || !body.prix || !body.categorieId) {
return NextResponse.json(
{ erreur: "Les champs nom, prix et categorieId sont requis." },
{ status: 400 }
);
}
Pour des validations plus avancées, vous pouvez utiliser une bibliothèque comme Zod :
import { z } from "zod";
const schemaProduit = z.object({
nom: z.string().min(1, "Le nom est requis"),
description: z.string().optional(),
prix: z.number().positive("Le prix doit être positif"),
categorieId: z.number().int("L'ID de catégorie doit être un entier"),
});
export async function POST(request: Request) {
const body = await request.json();
const resultat = schemaProduit.safeParse(body);
if (!resultat.success) {
return NextResponse.json(
{ erreurs: resultat.error.flatten().fieldErrors },
{ status: 400 }
);
}
// Les données sont validées, on peut les utiliser en toute sécurité
const produit = await prisma.produit.create({
data: resultat.data,
});
return NextResponse.json(produit, { status: 201 });
}
Réponses JSON¶
La classe NextResponse fournit des méthodes utilitaires pour créer des réponses HTTP :
import { NextResponse } from "next/server";
// Réponse avec données (200 par défaut)
return NextResponse.json({ nom: "Clavier" });
// Réponse avec code de statut personnalisé
return NextResponse.json(produit, { status: 201 });
// Réponse d'erreur
return NextResponse.json({ erreur: "Non trouvé" }, { status: 404 });