Învățați cum să creați endpoint-uri API puternice folosind Route Handlers în Next.js. Acest ghid acoperă totul, de la configurarea de bază la tehnici avansate, cu exemple practice și cele mai bune practici.
Route Handlers în Next.js: Un Ghid Complet pentru Crearea de Endpoint-uri API
Next.js a revoluționat modul în care construim aplicații web cu funcționalitățile sale puternice precum randarea pe server (server-side rendering), generarea de site-uri statice (static site generation) și, acum, Route Handlers. Route Handlers oferă o modalitate flexibilă și eficientă de a crea endpoint-uri API direct în aplicația dvs. Next.js. Acest ghid explorează conceptul de Route Handlers, beneficiile acestora și cum să le utilizați eficient pentru a construi API-uri robuste.
Ce sunt Route Handlers în Next.js?
Route Handlers sunt funcții definite în directorul app
al unui proiect Next.js care gestionează cererile HTTP primite. Spre deosebire de abordarea mai veche pages/api
(care utilizează API Routes), Route Handlers oferă o modalitate mai simplificată și flexibilă de a defini endpoint-uri API alături de componentele dvs. React. Acestea sunt în esență funcții serverless executate la edge sau în mediul de server ales de dvs.
Gândiți-vă la Route Handlers ca la logica de backend a aplicației dvs. Next.js, responsabilă pentru procesarea cererilor, interacțiunea cu bazele de date și returnarea răspunsurilor.
Beneficiile Utilizării Route Handlers
- Colocare: Route Handlers se află direct alături de componentele dvs. React în directorul
app
, promovând o mai bună organizare și mentenanță a codului. - Suport TypeScript: Suportul TypeScript integrat asigură siguranța tipurilor (type safety) și o experiență îmbunătățită pentru dezvoltatori.
- Integrare Middleware: Integrați cu ușurință middleware pentru sarcini precum autentificare, autorizare și validarea cererilor.
- Suport pentru Streaming: Route Handlers pot transmite date în flux (stream), permițându-vă să trimiteți răspunsuri incremental, ceea ce este benefic pentru seturi mari de date sau procese de lungă durată.
- Funcții Edge: Implementați Route Handlers ca Funcții Edge (Edge Functions) pentru răspunsuri cu latență redusă, mai aproape de utilizatorii dvs., profitând de CDN-uri globale.
- Design API Simplificat: Route Handlers oferă un API curat și intuitiv pentru gestionarea cererilor și răspunsurilor.
- Integrare cu Server Actions: Integrarea strânsă cu Acțiunile Server (Server Actions) permite o comunicare fluidă între componentele dvs. client-side și logica server-side.
Configurarea Proiectului Dvs. Next.js
Înainte de a explora Route Handlers, asigurați-vă că aveți un proiect Next.js configurat cu directorul app
. Dacă începeți un proiect nou, utilizați următoarea comandă:
npx create-next-app@latest my-nextjs-app
Alegeți directorul app
în timpul procesului de configurare pentru a activa noul sistem de rutare.
Crearea Primului Dvs. Route Handler
Să creăm un endpoint API simplu care returnează un răspuns JSON. Creați un nou director în interiorul directorului app
, de exemplu, /app/api/hello
. În acest director, creați un fișier numit route.ts
(sau route.js
dacă nu utilizați TypeScript).
Iată codul pentru primul dvs. Route Handler:
// app/api/hello/route.ts
import { NextResponse } from 'next/server';
export async function GET(request: Request) {
return NextResponse.json({ message: 'Salut de la Next.js Route Handlers!' });
}
Explicație:
import { NextResponse } from 'next/server';
: Importă obiectulNextResponse
, care este utilizat pentru a construi răspunsuri API.export async function GET(request: Request) { ... }
: Definește o funcție asincronă care gestionează cererile GET către endpoint-ul/api/hello
. Parametrulrequest
oferă acces la obiectul cererii primite.return NextResponse.json({ message: 'Salut de la Next.js Route Handlers!' });
: Creează un răspuns JSON cu un mesaj și îl returnează folosindNextResponse.json()
.
Acum, puteți accesa acest endpoint navigând la /api/hello
în browserul dvs. sau folosind un instrument precum curl
sau Postman
.
Gestionarea Diferitelor Metode HTTP
Route Handlers suportă diverse metode HTTP precum GET, POST, PUT, DELETE, PATCH și OPTIONS. Puteți defini funcții separate pentru fiecare metodă în același fișier route.ts
.
// app/api/users/route.ts
import { NextResponse } from 'next/server';
export async function GET(request: Request) {
// Logică pentru a prelua toți utilizatorii din baza de date
const users = [{ id: 1, name: 'John Doe' }, { id: 2, name: 'Jane Smith' }]; // Date exemplu
return NextResponse.json(users);
}
export async function POST(request: Request) {
const data = await request.json(); // Parsează corpul cererii ca JSON
// Logică pentru a crea un utilizator nou în baza de date folosind 'data'
const newUser = { id: 3, name: data.name, email: data.email }; // Exemplu
return NextResponse.json(newUser, { status: 201 }); // Returnează utilizatorul nou cu un cod de stare 201 Created
}
Explicație:
- Funcția
GET
preia o listă de utilizatori (simulată aici) și o returnează ca răspuns JSON. - Funcția
POST
parsează corpul cererii ca JSON, creează un utilizator nou (simulat) și returnează utilizatorul nou cu un cod de stare 201 Created.
Accesarea Datelor din Cerere
Obiectul request
oferă acces la diverse informații despre cererea primită, inclusiv antete, parametrii interogării și corpul cererii.
Antete (Headers)
Puteți accesa antetele cererii folosind proprietatea request.headers
:
export async function GET(request: Request) {
const userAgent = request.headers.get('user-agent');
console.log('User Agent:', userAgent);
return NextResponse.json({ userAgent });
}
Parametrii Interogării (Query Parameters)
Pentru a accesa parametrii interogării, puteți utiliza constructorul URL
:
export async function GET(request: Request) {
const url = new URL(request.url);
const searchParams = new URLSearchParams(url.search);
const id = searchParams.get('id');
console.log('ID:', id);
return NextResponse.json({ id });
}
Corpul Cererii (Request Body)
Pentru cererile POST, PUT și PATCH, puteți accesa corpul cererii folosind metodele request.json()
sau request.text()
, în funcție de tipul de conținut.
export async function POST(request: Request) {
const data = await request.json();
console.log('Date:', data);
return NextResponse.json({ receivedData: data });
}
Returnarea Răspunsurilor
Obiectul NextResponse
este utilizat pentru a construi răspunsuri API. Acesta oferă mai multe metode pentru setarea antetelor, codurilor de stare și corpurilor de răspuns.
Răspunsuri JSON
Utilizați metoda NextResponse.json()
pentru a returna răspunsuri JSON:
return NextResponse.json({ message: 'Succes!', data: { name: 'John Doe' } }, { status: 200 });
Răspunsuri Text
Utilizați constructorul new Response()
pentru a returna răspunsuri text simplu:
return new Response('Salut, lume!', { status: 200, headers: { 'Content-Type': 'text/plain' } });
Redirecționări
Utilizați NextResponse.redirect()
pentru a redirecționa utilizatorii către o altă adresă URL:
import { redirect } from 'next/navigation';
import { NextResponse } from 'next/server';
export async function GET(request: Request) {
return NextResponse.redirect(new URL('/new-location', request.url));
}
Setarea Antetelor (Headers)
Puteți seta antete personalizate folosind opțiunea headers
în NextResponse.json()
sau new Response()
:
return NextResponse.json({ message: 'Succes!' }, { status: 200, headers: { 'Cache-Control': 'no-cache' } });
Integrarea Middleware
Middleware-ul vă permite să rulați cod înainte ca o cerere să fie gestionată de Route Handler-ul dvs. Acest lucru este util pentru autentificare, autorizare, logging și alte preocupări transversale.
Pentru a crea un middleware, creați un fișier numit middleware.ts
(sau middleware.js
) în directorul app
sau în orice subdirector. Middleware-ul se va aplica tuturor rutelor din acel director și subdirectoarele sale.
// app/middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
export function middleware(request: NextRequest) {
const token = request.cookies.get('auth-token');
if (!token) {
return NextResponse.redirect(new URL('/login', request.url));
}
return NextResponse.next();
}
export const config = {
matcher: ['/protected/:path*'], // Aplică acest middleware pe căile care încep cu /protected/
};
Explicație:
- Funcția
middleware
verifică existența unui token de autentificare în cookie-urile cererii. - Dacă tokenul lipsește, redirecționează utilizatorul către pagina de login.
- În caz contrar, permite cererii să continue către Route Handler.
- Obiectul
config
specifică faptul că acest middleware ar trebui să se aplice numai rutelor care încep cu/protected/
.
Gestionarea Erorilor
Gestionarea corectă a erorilor este crucială pentru construirea de API-uri robuste. Puteți utiliza blocuri try...catch
pentru a gestiona excepțiile și a returna răspunsuri de eroare corespunzătoare.
export async function GET(request: Request) {
try {
// Simulează o eroare
throw new Error('Ceva nu a mers bine!');
} catch (error: any) {
console.error('Eroare:', error);
return NextResponse.json({ error: error.message }, { status: 500 });
}
}
Explicație:
- Blocul
try...catch
prinde orice excepție care apare în cadrul Route Handler-ului. - În blocul
catch
, eroarea este înregistrată în consolă, și se returnează un răspuns de eroare cu un cod de stare 500 Internal Server Error.
Răspunsuri în Flux (Streaming)
Route Handlers suportă răspunsuri în flux (streaming), ceea ce vă permite să trimiteți date incremental către client. Acest lucru este deosebit de util pentru seturi mari de date sau procese de lungă durată.
import { Readable } from 'stream';
import { NextResponse } from 'next/server';
async function* generateData() {
for (let i = 0; i < 10; i++) {
await new Promise(resolve => setTimeout(resolve, 500)); // Simulează o întârziere
yield `Bucată de date ${i}\n`;
}
}
export async function GET(request: Request) {
const readableStream = Readable.from(generateData());
return new Response(readableStream, {
headers: { 'Content-Type': 'text/plain; charset=utf-8' },
});
}
Explicație:
- Funcția
generateData
este un generator asincron care produce bucăți de date cu o întârziere. - Metoda
Readable.from()
creează un flux citibil (readable stream) din generator. - Obiectul
Response
este creat cu fluxul citibil ca și corp, iar antetulContent-Type
este setat latext/plain
.
Autentificare și Autorizare
Securizarea endpoint-urilor API este crucială. Puteți implementa autentificarea și autorizarea folosind middleware sau direct în cadrul Route Handlers.
Autentificare
Autentificarea verifică identitatea utilizatorului care face cererea. Metodele comune de autentificare includ:
- JWT (JSON Web Tokens): Generați un token la autentificarea cu succes și verificați-l la cererile ulterioare.
- Autentificare bazată pe sesiune: Utilizați cookie-uri pentru a stoca identificatori de sesiune și verificați-i la fiecare cerere.
- OAuth: Delegați autentificarea către un furnizor terț precum Google sau Facebook.
Iată un exemplu de autentificare JWT folosind middleware:
// app/middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
import jwt from 'jsonwebtoken';
const secret = process.env.JWT_SECRET || 'your-secret-key'; // Înlocuiți cu un secret puternic, generat aleatoriu
export function middleware(request: NextRequest) {
const token = request.cookies.get('auth-token')?.value;
if (!token) {
return NextResponse.json({ message: 'Autentificare necesară' }, { status: 401 });
}
try {
jwt.verify(token, secret);
return NextResponse.next();
} catch (error) {
return NextResponse.json({ message: 'Token invalid' }, { status: 401 });
}
}
export const config = {
matcher: ['/api/protected/:path*'],
};
Autorizare
Autorizarea determină la ce resurse are acces un utilizator. Aceasta se bazează de obicei pe roluri sau permisiuni.
Puteți implementa autorizarea în cadrul Route Handlers prin verificarea rolurilor sau permisiunilor utilizatorului și returnarea unei erori dacă acesta nu are acces.
// app/api/admin/route.ts
import { NextResponse } from 'next/server';
export async function GET(request: Request) {
// Presupunem că aveți o funcție pentru a obține rolul utilizatorului din token sau sesiune
const userRole = await getUserRole(request);
if (userRole !== 'admin') {
return NextResponse.json({ message: 'Neautorizat' }, { status: 403 });
}
// Logică pentru a prelua date de administrator
const adminData = { message: 'Date de administrator' };
return NextResponse.json(adminData);
}
async function getUserRole(request: Request): Promise {
// Înlocuiți cu logica dvs. reală pentru a extrage rolul utilizatorului din cerere
// Aceasta ar putea implica verificarea unui token JWT sau verificarea unei sesiuni
return 'admin'; // Exemplu: rol codat direct pentru demonstrație
}
Implementarea (Deploying) Route Handlers
Route Handlers sunt implementate ca funcții serverless pe furnizorul dvs. de găzduire ales. Next.js suportă diverse platforme de implementare, inclusiv Vercel, Netlify, AWS și altele.
Pentru Vercel, implementarea este la fel de simplă ca și conectarea depozitului Git la Vercel și trimiterea codului. Vercel detectează automat proiectul dvs. Next.js și implementează Route Handlers ca funcții serverless.
Tehnici Avansate
Funcții Edge
Route Handlers pot fi implementate ca Funcții Edge (Edge Functions), care sunt executate la marginea unei rețele CDN, mai aproape de utilizatorii dvs. Acest lucru poate reduce semnificativ latența și îmbunătăți performanța.
Pentru a implementa un Route Handler ca Funcție Edge, adăugați runtime-ul edge
în fișierul dvs. route.ts
:
export const runtime = 'edge';
import { NextResponse } from 'next/server';
export async function GET(request: Request) {
return NextResponse.json({ message: 'Salut de la Edge!' });
}
Acțiuni Server (Server Actions)
Acțiunile Server (Server Actions) vă permit să executați cod server-side direct din componentele dvs. React. Route Handlers și Server Actions funcționează perfect împreună, permițându-vă să construiți aplicații complexe cu ușurință.
Iată un exemplu de utilizare a unei Acțiuni Server pentru a apela un Route Handler:
// app/components/MyComponent.tsx
'use client';
import { useState } from 'react';
import { useRouter } from 'next/navigation';
async function handleSubmit(data: FormData) {
'use server';
const name = data.get('name');
const email = data.get('email');
const response = await fetch('/api/users', {
method: 'POST',
body: JSON.stringify({ name, email }),
});
if (response.ok) {
router.refresh(); // Reîmprospătează pagina pentru a reflecta schimbările
}
}
export default function MyComponent() {
const router = useRouter();
return (
);
}
Caching (Memorare în Cache)
Memorarea în cache (caching) poate îmbunătăți semnificativ performanța endpoint-urilor API. Puteți utiliza antetul Cache-Control
pentru a controla modul în care răspunsurile dvs. sunt memorate în cache de către browsere și CDN-uri.
return NextResponse.json({ message: 'Succes!' }, { status: 200, headers: { 'Cache-Control': 'public, max-age=3600' } });
Acest exemplu setează antetul Cache-Control
la public, max-age=3600
, ceea ce indică browserelor și CDN-urilor să memoreze în cache răspunsul timp de o oră.
Cele Mai Bune Practici
- Utilizați TypeScript: Profitați de siguranța tipurilor din TypeScript pentru a îmbunătăți calitatea codului și a preveni erorile.
- Validați Cererile: Validați cererile primite pentru a asigura integritatea datelor și a preveni intrările malițioase.
- Gestionați Erorile Elegant: Implementați o gestionare adecvată a erorilor pentru a oferi mesaje de eroare informative clienților.
- Securizați Endpoint-urile: Implementați autentificare și autorizare pentru a vă proteja endpoint-urile API.
- Utilizați Middleware: Folosiți middleware pentru preocupări transversale precum autentificarea, logging-ul și validarea cererilor.
- Memorați Răspunsurile în Cache: Utilizați caching pentru a îmbunătăți performanța endpoint-urilor API.
- Monitorizați API-urile: Monitorizați API-urile pentru a identifica și rezolva problemele rapid.
- Documentați API-urile: Documentați API-urile pentru a le face ușor de utilizat de către alți dezvoltatori. Luați în considerare utilizarea unor instrumente precum Swagger/OpenAPI pentru documentația API.
Exemple din Lumea Reală
Iată câteva exemple din lumea reală despre cum pot fi utilizate Route Handlers:
- API pentru E-commerce: Creați endpoint-uri API pentru gestionarea produselor, comenzilor și utilizatorilor.
- API pentru Rețele Sociale: Creați endpoint-uri API pentru postarea de tweet-uri, urmărirea utilizatorilor și preluarea cronologiilor.
- API pentru Sistem de Management al Conținutului (CMS): Creați endpoint-uri API pentru gestionarea conținutului, utilizatorilor și setărilor.
- API pentru Analiza Datelor: Creați endpoint-uri API pentru colectarea și analiza datelor. De exemplu, un Route Handler ar putea primi date de la pixeli de urmărire de pe diferite site-uri web și agrega informațiile pentru raportare.
Exemplu de E-commerce Internațional: Un Route Handler folosit pentru a prelua prețurile produselor în funcție de țara utilizatorului. Endpoint-ul ar putea folosi geolocația cererii (derivată din adresa IP) pentru a determina locația utilizatorului și a returna prețuri în moneda corespunzătoare. Acest lucru contribuie la o experiență de cumpărături localizată.
Exemplu de Autentificare Globală: Un Route Handler care implementează autentificarea multi-factor (MFA) pentru utilizatori din întreaga lume. Acest lucru ar putea implica trimiterea de coduri SMS sau utilizarea de aplicații de autentificare, respectând în același timp reglementările privind confidențialitatea și infrastructurile de telecomunicații din diferite regiuni.
Livrarea de Conținut Multilingv: Un Route Handler care livrează conținut în limba preferată a utilizatorului. Aceasta poate fi determinată din antetul `Accept-Language` din cerere. Acest exemplu evidențiază necesitatea unei codificări UTF-8 corespunzătoare și a suportului pentru limbi de la dreapta la stânga, acolo unde este cazul.
Concluzie
Route Handlers din Next.js oferă o modalitate puternică și flexibilă de a crea endpoint-uri API direct în aplicația dvs. Next.js. Prin utilizarea Route Handlers, puteți construi API-uri robuste cu ușurință, puteți colocaliza logica de backend cu componentele React și puteți profita de funcționalități precum middleware, streaming și Funcții Edge.
Acest ghid cuprinzător a acoperit totul, de la configurarea de bază la tehnici avansate. Urmând cele mai bune practici prezentate în acest ghid, puteți construi API-uri de înaltă calitate, care sunt sigure, performante și ușor de întreținut.