Darylngako
11/11/20240 🇫🇷

Comprendre les API Routes et les Route Handlers dans NextJS

Ecris par Ngako Daryl le 11 novembre 2024

Une API (Application programming Interface) est un ensemble de points de terminaison ou endpoints côté serveur qui vous permet de gérer des requêtes et fournir des données à votre application. C'est quoi une APi Route? C'est quoi une Route Handler? Nous verrons cela ensemble.

Les API Routes: La Solution Classique

Les API Routes sont l'approche traditionnelle pour gérer les endpoints dans NextJS. Elles ont été conçues pour fonctionner dans le modèle de routage basé sur les pages.

Où construire les API Routes?

Les API Routes sont créées dans le dossier pages/api. Chaque fichier dans ce dossier devient un endpoint d'API avec le nom du fichier comme URL.

Par exemple...

pages/api/user.ts correspond à l'URL /api/user.

Syntaxe

Chaque API Route est essentiellement une fonction JavaScript ou TypeScript qui exporte un handler. Cette fonction accepte un objet req (requête) et res (réponse) pour gérer la logique de l'API.

pages/api/user.ts
ts
import { NextApiRequest, NextApiResponse } from "next";
export default function handler(req: NextApiRequest, res: NextApiResponse) {
  if (req.method === "GET") {
    res.status(200).json({ message: "hello Word!" });
  }
}

Les Route Handlers : La Nouvelle Génération d'endpoints

Avec la sortie du modèle App Router dans Next.js, une approche plus avancée est apparue: les Route Handlers. Conçus pour les projets qui utilisent le dossier app, ils permettent une meilleure organisation des endpoints.

Où construire les Routes Handlers?

Les Route Handlers se trouvent dans le dossier app. Ils sont définis dans des fichiers route.ts ou route.js placés à l'intérieur de dossiers correspondant aux routes.

app_router_structure
dddd

Syntaxe

Les Routes handlers (en français gestionnaire d'itinéraire) comme son nom l'indique vont permettre de créer une itinéraire spécifique pour chaque méthode HTTP (GET, POST, etc...). Ce qui rend le code plus lisible et modulaire.

app/api/user/route.ts
ts
export async function GET(req: Request) {
  return new Response("hello word!", { status: 200 });
}
 
export async function POST(req: Request) {
  const data = await req.json();
  return new Response(JSON.stringify({ data }), { status: 200 });
}

API Routes VS Routes Handlers

Envoyer une réponse JSON

JSON (JavaScript Object Notation) est un format de texte simple et léger utilisé souvent pour échanger des données entre le client et le serveur web.

json
{
  "nom": "daryl",
  "âge": 20
}

La réponse retournée par le serveur au client doit être une réponse JSON.

Exemple dans le dossier Pages

pages/api/identity.ts
ts
import {NextApiResponse } from "next";
 
export default function handler(res:NextApiResponse) {
 const user = {id:2, name:"daryl"}
  return res.json({user});
}

Exemple dans le dossier App

app/api/identity/route.ts
ts
import {NextResponse } from "next/server";
export default function GET(req:Request) {
 const user = {id:2, name:"daryl"}
 return NextResponse.json({user}) 
}

Les routes dynamiques

une route dynamique permet de créer des pages ou des API qui peuvent changer en fonction de paramètres dynamiques comme des identifiants d'articles, l'identifiant d'un utilisateur, etc... Ces routes sont utiles pour gérer des contenus uniques basés sur des paramètres.

Par exemple...

Une API qui retourne les informations d'un utilisateur spécifique en fonction de son identifiant.

Exemple de route dynamique dans le dossier Pages

Supposons que tu souhaites créer une API pour afficher les informations des utilisateurs en fonction de leur identifiant.

Tu crées la route comme suit:

users_page_router
Exemple de route dynamique dans le dossier Pages

Le nom [id].ts indique que id est un paramètre dynamique dans la route /users/[id]. Par exemple, les URLs /users/1 ou users/2** vont toutes deux utiliser ce fichier pour générer la route API.

Ensuite nous accédons à la valeur:

pages/api/users/[id].ts
ts
import { NextApiRequest, NextApiResponse } from "next";
import users from "./users"
export default function handler(req:NextApiRequest, res:NextApiResponse) {
  const { id } = req.query;
  const user = users.find((user) => user.id === id)
  return res.status(200).json({user});
}

Exemple de route dynamique dans le Dossier App

Reprenons le même exemple, cette fois-ci dans le dossier App.

Tu crées la route comme suit:

users_app_router
Exemple de route dynamique dans le dossier App

Ensuite nous accédons à la valeur:

app/api/users/[id]/route.ts
ts
import users from "./users"
export async function GET(req:Request,{ params }: { params: Promise<{ id: string }> }) {
 const userId = (await params).id
const user = users.find((user) => user.id === id)
  return new Response(user,{
   status: 200
  })   
}

Les paramètres de requêtes URL

Les paramètres passés à l'URL vont pouvoir être récupéré avec l'objet Request passé en paramètre.

Exemple dans le dossier Pages

ts
 
export default function handler(req:Request) {
  const paramsSearch = req.url;
 //For the URL /api/search?q=hello paramsSearch is an object which contains the property q which has the value "hello"
  return new Response(query)   
}

Exemple dans le dossier App

app/api/search/route.ts
ts
 
export default function GET(req:Request) {
  const { searchParams } = new URL(req.url);
  const query = searchParams.get("query");
//query is "hello" for /api/search?q=hello
 
  return new Response(query)   
}

Les paramètres passés dans le corps de la requête

Tu peux lire les paramètres passés dans le corps d'une requête (le body) API.

Exemple dans le dossier Pages

pages/api/create-product.ts
ts
import { NextApiRequest, NextApiResponse } from "next";
 
export default function handler(req:NextApiRequest) {
  const product = req.body;
  //product is an object which contains properties like id, name and description
  try {
    // I use prisma for create product in the database
     const result = await prisma.product.create({
    data:{product}
  }) 
    return res.status(200).send({result});
  } catch (error) {
   return res.status(500).send({ error: 'failed to create product' })
  } 
}

Exemple avec le dossier APP

app/api/create-product/route.ts
ts
import { NextApiRequest, NextApiResponse } from "next";
 
export async function POST(req:Request) {
 
  const product = await req.json();
  //product is an object which contains properties like id, name and description
  try {
    const result = await prisma.product.create({
    data:{product}
  }) 
   return Response.json({ result })
  } catch (error) {
    return Response.error()
  }
  
}

Différence entre les API Routes et les Routes Habndlers

Contrairement aux Routes Handlers, les API Routes sont faciles à configurer et à comprendre surtout pour des développeurs qui ont déja eu à utiliser Express. Mais les Routes handlers permettent de définir chaque méthode HTTP séparémment rendant le code plus lisible.

Voici une image ci-dessous qui illustre une comparaison entre ces deux approches:

users_app_router
API Routes vs Routes Handlers

Conclusion