Italiano

Impara a creare potenti endpoint API con i Route Handler di Next.js. Questa guida copre tutto, dalla configurazione base alle tecniche avanzate, con esempi pratici e best practice.

Route Handler di Next.js: Una Guida Completa alla Creazione di Endpoint API

Next.js ha rivoluzionato il modo in cui costruiamo applicazioni web con le sue potenti funzionalità come il rendering lato server, la generazione di siti statici e, ora, i Route Handler. I Route Handler forniscono un modo flessibile ed efficiente per creare endpoint API direttamente all'interno della tua applicazione Next.js. Questa guida esplora il concetto di Route Handler, i loro vantaggi e come utilizzarli efficacemente per costruire API robuste.

Cosa sono i Route Handler di Next.js?

I Route Handler sono funzioni definite all'interno della directory app di un progetto Next.js che gestiscono le richieste HTTP in arrivo. A differenza del vecchio approccio pages/api (che utilizza le API Routes), i Route Handler offrono un modo più snello e flessibile per definire gli endpoint API accanto ai tuoi componenti React. Sono essenzialmente funzioni serverless eseguite sull'edge o nell'ambiente server da te scelto.

Pensa ai Route Handler come alla logica di backend della tua applicazione Next.js, responsabile dell'elaborazione delle richieste, dell'interazione con i database e della restituzione delle risposte.

Vantaggi dell'uso dei Route Handler

Configurare il tuo progetto Next.js

Prima di immergerti nei Route Handler, assicurati di avere un progetto Next.js configurato con la directory app. Se stai iniziando un nuovo progetto, usa il seguente comando:

npx create-next-app@latest my-nextjs-app

Scegli la directory app durante il processo di configurazione per abilitare il nuovo sistema di routing.

Creare il tuo primo Route Handler

Creiamo un semplice endpoint API che restituisce una risposta JSON. Crea una nuova directory all'interno della directory app, ad esempio, /app/api/hello. All'interno di questa directory, crea un file chiamato route.ts (o route.js se non stai usando TypeScript).

Ecco il codice per il tuo primo Route Handler:

// app/api/hello/route.ts
import { NextResponse } from 'next/server';

export async function GET(request: Request) {
 return NextResponse.json({ message: 'Ciao dai Route Handler di Next.js!' });
}

Spiegazione:

Ora, puoi accedere a questo endpoint navigando su /api/hello nel tuo browser o usando uno strumento come curl o Postman.

Gestire i diversi metodi HTTP

I Route Handler supportano vari metodi HTTP come GET, POST, PUT, DELETE, PATCH e OPTIONS. Puoi definire funzioni separate per ogni metodo all'interno dello stesso file route.ts.

// app/api/users/route.ts
import { NextResponse } from 'next/server';

export async function GET(request: Request) {
 // Logica per recuperare tutti gli utenti dal database
 const users = [{ id: 1, name: 'John Doe' }, { id: 2, name: 'Jane Smith' }]; // Dati di esempio
 return NextResponse.json(users);
}

export async function POST(request: Request) {
 const data = await request.json(); // Esegue il parsing del corpo della richiesta come JSON
 // Logica per creare un nuovo utente nel database usando 'data'
 const newUser = { id: 3, name: data.name, email: data.email }; // Esempio
 return NextResponse.json(newUser, { status: 201 }); // Restituisce il nuovo utente con un codice di stato 201 Created
}

Spiegazione:

Accedere ai dati della richiesta

L'oggetto request fornisce accesso a varie informazioni sulla richiesta in arrivo, inclusi header, parametri di query e il corpo della richiesta.

Header

Puoi accedere agli header della richiesta usando la proprietà request.headers:

export async function GET(request: Request) {
 const userAgent = request.headers.get('user-agent');
 console.log('User Agent:', userAgent);
 return NextResponse.json({ userAgent });
}

Parametri di query

Per accedere ai parametri di query, puoi usare il costruttore 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 });
}

Corpo della richiesta

Per le richieste POST, PUT e PATCH, puoi accedere al corpo della richiesta usando i metodi request.json() o request.text(), a seconda del tipo di contenuto.

export async function POST(request: Request) {
 const data = await request.json();
 console.log('Data:', data);
 return NextResponse.json({ receivedData: data });
}

Restituire le risposte

L'oggetto NextResponse è usato per costruire le risposte API. Fornisce diversi metodi per impostare header, codici di stato e corpi delle risposte.

Risposte JSON

Usa il metodo NextResponse.json() per restituire risposte JSON:

return NextResponse.json({ message: 'Success!', data: { name: 'John Doe' } }, { status: 200 });

Risposte testuali

Usa il costruttore new Response() per restituire risposte di testo semplice:

return new Response('Ciao, mondo!', { status: 200, headers: { 'Content-Type': 'text/plain' } });

Reindirizzamenti

Usa NextResponse.redirect() per reindirizzare gli utenti a un URL diverso:

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));
}

Impostare gli header

Puoi impostare header personalizzati usando l'opzione headers in NextResponse.json() o new Response():

return NextResponse.json({ message: 'Success!' }, { status: 200, headers: { 'Cache-Control': 'no-cache' } });

Integrazione dei Middleware

Il middleware ti permette di eseguire codice prima che una richiesta venga gestita dal tuo Route Handler. Questo è utile per l'autenticazione, l'autorizzazione, il logging e altre problematiche trasversali.

Per creare un middleware, crea un file chiamato middleware.ts (o middleware.js) nella directory app o in qualsiasi sottodirectory. Il middleware si applicherà a tutte le route all'interno di quella directory e delle sue sottodirectory.

// 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*'], // Applica questo middleware ai percorsi che iniziano con /protected/
};

Spiegazione:

Gestione degli errori

Una corretta gestione degli errori è cruciale per costruire API robuste. Puoi usare i blocchi try...catch per gestire le eccezioni e restituire risposte di errore appropriate.

export async function GET(request: Request) {
 try {
 // Simula un errore
 throw new Error('Qualcosa è andato storto!');
 } catch (error: any) {
 console.error('Errore:', error);
 return NextResponse.json({ error: error.message }, { status: 500 });
 }
}

Spiegazione:

Risposte in streaming

I Route Handler supportano le risposte in streaming, che ti permettono di inviare dati in modo incrementale al client. Questo è particolarmente utile per grandi set di dati o processi di lunga durata.

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)); // Simula un ritardo
 yield `Blocco di dati ${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' },
 });
}

Spiegazione:

Autenticazione e Autorizzazione

Mettere in sicurezza i tuoi endpoint API è cruciale. Puoi implementare l'autenticazione e l'autorizzazione usando middleware o direttamente all'interno dei tuoi Route Handler.

Autenticazione

L'autenticazione verifica l'identità dell'utente che effettua la richiesta. I metodi di autenticazione comuni includono:

Ecco un esempio di autenticazione JWT tramite 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 || 'la-tua-chiave-segreta'; // Sostituisci con un segreto forte e generato casualmente

export function middleware(request: NextRequest) {
 const token = request.cookies.get('auth-token')?.value;

 if (!token) {
 return NextResponse.json({ message: 'Autenticazione richiesta' }, { status: 401 });
 }

 try {
 jwt.verify(token, secret);
 return NextResponse.next();
 } catch (error) {
 return NextResponse.json({ message: 'Token non valido' }, { status: 401 });
 }
}

export const config = {
 matcher: ['/api/protected/:path*'],
};

Autorizzazione

L'autorizzazione determina a quali risorse un utente è autorizzato ad accedere. Questo si basa tipicamente su ruoli o permessi.

Puoi implementare l'autorizzazione all'interno dei tuoi Route Handler controllando i ruoli o i permessi dell'utente e restituendo un errore se non hanno accesso.

// app/api/admin/route.ts
import { NextResponse } from 'next/server';

export async function GET(request: Request) {
 // Assumiamo che tu abbia una funzione per ottenere il ruolo dell'utente dal token o dalla sessione
 const userRole = await getUserRole(request);

 if (userRole !== 'admin') {
 return NextResponse.json({ message: 'Non autorizzato' }, { status: 403 });
 }

 // Logica per recuperare i dati dell'amministratore
 const adminData = { message: 'Dati amministratore' };
 return NextResponse.json(adminData);
}

async function getUserRole(request: Request): Promise {
 // Sostituisci con la tua logica effettiva per estrarre il ruolo dell'utente dalla richiesta
 // Questo potrebbe comportare la verifica di un token JWT o il controllo di una sessione
 return 'admin'; // Esempio: ruolo hardcoded per dimostrazione
}

Deployment dei Route Handler

I Route Handler vengono distribuiti come funzioni serverless sul tuo provider di hosting prescelto. Next.js supporta varie piattaforme di deployment, tra cui Vercel, Netlify, AWS e altre.

Per Vercel, il deployment è semplice come collegare il tuo repository Git a Vercel e inviare il tuo codice. Vercel rileva automaticamente il tuo progetto Next.js e distribuisce i tuoi Route Handler come funzioni serverless.

Tecniche Avanzate

Edge Functions

I Route Handler possono essere distribuiti come Edge Functions, che vengono eseguite sull'edge di una CDN, più vicino ai tuoi utenti. Questo può ridurre significativamente la latenza e migliorare le prestazioni.

Per distribuire un Route Handler come Edge Function, aggiungi il runtime edge al tuo file route.ts:

export const runtime = 'edge';

import { NextResponse } from 'next/server';

export async function GET(request: Request) {
 return NextResponse.json({ message: 'Ciao dall\'Edge!' });
}

Server Actions

Le Server Actions ti permettono di eseguire codice lato server direttamente dai tuoi componenti React. I Route Handler e le Server Actions funzionano perfettamente insieme, permettendoti di costruire applicazioni complesse con facilità.

Ecco un esempio di utilizzo di una Server Action per chiamare 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(); // Aggiorna la pagina per riflettere le modifiche
 }
}

export default function MyComponent() {
 const router = useRouter();

 return (
 




); }

Caching

Il caching può migliorare significativamente le prestazioni dei tuoi endpoint API. Puoi usare l'header Cache-Control per controllare come le tue risposte vengono memorizzate nella cache dai browser e dalle CDN.

return NextResponse.json({ message: 'Success!' }, { status: 200, headers: { 'Cache-Control': 'public, max-age=3600' } });

Questo esempio imposta l'header Cache-Control su public, max-age=3600, che indica ai browser e alle CDN di memorizzare la risposta nella cache per un'ora.

Best Practice

Esempi dal mondo reale

Ecco alcuni esempi reali di come possono essere usati i Route Handler:

Esempio di E-commerce internazionale: Un Route Handler utilizzato per recuperare i prezzi dei prodotti in base al paese dell'utente. L'endpoint potrebbe usare la geolocalizzazione della richiesta (derivata dall'indirizzo IP) per determinare la posizione dell'utente e restituire i prezzi nella valuta appropriata. Questo contribuisce a un'esperienza di acquisto localizzata.

Esempio di Autenticazione globale: Un Route Handler che implementa l'autenticazione a più fattori (MFA) per utenti in tutto il mondo. Questo potrebbe comportare l'invio di codici SMS o l'uso di app di autenticazione, nel rispetto delle normative sulla privacy e delle infrastrutture di telecomunicazione delle diverse regioni.

Distribuzione di contenuti multilingue: Un Route Handler che fornisce contenuti nella lingua preferita dell'utente. Questa può essere determinata dall'header `Accept-Language` nella richiesta. Questo esempio evidenzia la necessità di una corretta codifica UTF-8 e del supporto per le lingue da destra a sinistra, se appropriato.

Conclusione

I Route Handler di Next.js forniscono un modo potente e flessibile per creare endpoint API direttamente all'interno della tua applicazione Next.js. Sfruttando i Route Handler, puoi costruire API robuste con facilità, collocare la logica di backend insieme ai tuoi componenti React e approfittare di funzionalità come middleware, streaming e Edge Functions.

Questa guida completa ha coperto tutto, dalla configurazione di base alle tecniche avanzate. Seguendo le best practice delineate in questa guida, puoi costruire API di alta qualità che siano sicure, performanti e manutenibili.