API Route Next.js (Route Handler): GET, POST, Auth | We.Inc
Esempi di Route Handler Next.js per l'App Router da copiare: GET con parametri di query, POST con validazione, parametri dinamici come promise, controlli di autenticazione, CORS e webhook.
Nell'App Router, un endpoint API è un file route.ts dentro app, per esempio app/api/todos/route.ts. Esporta funzioni async con il nome dei metodi HTTP, come GET e POST; ognuna riceve una Request e restituisce una Response, di solito Response.json(). I segmenti dinamici arrivano come una promise params da attendere con await. Da Next.js 15 gli handler GET sono dinamici per impostazione predefinita.
Basi dei Route Handler
Operazione
Codice
Restituire JSON
return Response.json(data, { status: 200 })
Leggere un body JSON
const body = await request.json()
Leggere dati di un form
const form = await request.formData()
Leggere ?q=
request.nextUrl.searchParams.get("q")
Segmento dinamico
const { id } = await params
Cookie / header
await cookies(), await headers() from next/headers
Le API route del Pages Router usavano gli oggetti req e res. I Route Handler usano invece gli standard Web Request e Response, e questo manda in confusione chi copia risposte più vecchie. Qui sotto trovi i pattern che ti servono per un'app reale, ognuno scritto per l'App Router attuale, più un piccolo tester che mostra i codici di stato che un POST con validazione dovrebbe restituire.
Compila il body di richiesta fittizio nel tester e scegli se il chiamante ha effettuato l'accesso.
Il tester applica nel tuo browser le stesse regole di validazione dell'esempio POST di questa pagina.
Leggi il codice di stato e il JSON restituiti, poi modifica un campo per vedere un 400, 401 o 201.
Copia l'handler di esempio e sostituisci la lista in memoria con il tuo database.
Tratta ogni handler come un endpoint pubblico. Controlla la sessione dentro l'handler anche se il proxy ha già reindirizzato gli utenti non autenticati.
Valida il body con una libreria di schema come Zod e invia un 400 con gli errori dei campi, invece di lasciare che un payload sbagliato generi un 500.
Un file route.ts non può stare nella stessa cartella di un page.tsx; metti le API sotto app/api per tenerle separate.
Se non esporti OPTIONS, Next.js risponde al posto tuo con un header Allow che elenca i metodi che hai esportato.
Per i webhook, leggi il body grezzo con request.text() prima del parsing, perché la verifica della firma richiede i byte esatti.
Domande frequenti
Le API route di Next.js sono deprecate?
Le route pages/api funzionano ancora nel Pages Router. Nell'App Router l'equivalente è un Route Handler, un file route.ts che usa gli oggetti Web Request e Response e non richiede alcuna configurazione di bodyParser.
Quali metodi HTTP può esportare un route.ts?
GET, POST, PUT, PATCH, DELETE, HEAD e OPTIONS. Chiamare un metodo che non hai esportato restituisce 405 Method Not Allowed.
Perché devo usare await su params?
Da Next.js 15, params nell'argomento context è una promise. Scrivi const { id } = await params. Il tipo helper RouteContext, generato da next dev, next build o next typegen, ti dà params tipizzati a partire dal percorso della route.
I Route Handler GET vengono messi in cache?
Non più per impostazione predefinita. Next.js 15 ha reso gli handler GET dinamici invece che statici. Puoi riattivare la cache con export const dynamic = 'force-static' o un valore di revalidate. Con Cache Components attivo, metti use cache in una funzione helper chiamata dall'handler, non nel corpo dell'handler.
Meglio un Route Handler o una Server Action?
Usa una Server Action per le modifiche attivate dai tuoi form e pulsanti. Usa un Route Handler quando qualcosa al di fuori del tuo albero React chiama l'URL: un'app mobile, un webhook, un cron job o uno script di terze parti.
Struttura dei file
Il percorso della cartella è l'URL. app/api/todos/route.ts risponde a /api/todos, e app/api/todos/[id]/route.ts risponde a /api/todos/42. Una cartella catch-all come [...slug] passa un array di segmenti.
I Route Handler condividono la configurazione dei segmenti con le pagine, quindi valgono anche per loro gli stessi export dynamic, revalidate e runtime.
Codici di stato che i client capiscono
Invia 201 dopo aver creato qualcosa, 400 quando l'input è sbagliato, 401 quando nessuno ha effettuato l'accesso, 403 quando l'utente autenticato non ha i permessi, 404 quando il record non esiste e 405 per i metodi non supportati. Così il front end può decidere in base al codice invece di analizzare il testo dell'errore.
Restituisci una forma JSON coerente per gli errori, come { error: string, fields?: object }, così un unico helper di fetch può gestirli tutti.
Checklist di sicurezza
Verifica la sessione, controlla che l'utente sia il proprietario del record che sta modificando, valida il payload e non restituire mai segreti o righe utente complete. La guida ufficiale all'autenticazione mostra questo schema in due passaggi: un 401 se non c'è sessione e un 403 per il ruolo sbagliato.
Imposta gli header CORS solo sugli handler che altre origini devono davvero chiamare, ed elenca le origini specifiche invece di un asterisco ogni volta che sono coinvolti i cookie.
Esempi di Route Handler
GET con una query di ricerca
app/api/todos/route.ts. Il parametro q filtra la lista; una query vuota restituisce tutto.
POST con validazione Zod e controllo di autenticazione
Restituisce 401 senza sessione, 400 con gli errori dei campi per un body non valido, altrimenti 201 con il nuovo record. getSession sta al posto della tua libreria di autenticazione.
Segmento dinamico con params attesi
app/api/todos/[id]/route.ts. params è una promise da Next.js 15 in poi.
CORS per un'unica origine fidata
Risponde alla richiesta preflight del browser e alla richiesta vera con la stessa origine consentita.
Chiamare l'handler da un Client Component
L'helper di fetch legge prima il codice di stato, così il form può mostrare gli errori dei campi di un 400.
API route del Pages Router e Route Handler a confronto
Stesso lavoro, API diverse
pages/api/x.ts
app/api/x/route.ts
Handler
export default function handler(req, res)
export async function GET(request)
Inviare JSON
res.status(200).json(data)
return Response.json(data)
Gestione del metodo
if (req.method === "POST")
una funzione POST esportata a parte
Parsing del body
req.body (configurazione bodyParser)
await request.json() o request.formData()
Query string
request.nextUrl.searchParams
Tester POST
Modifica un body JSON, scegli se il chiamante ha effettuato l'accesso e guarda il codice di stato e la risposta che l'esempio POST con validazione restituirebbe.
Metodo
Body della richiesta (JSON)
Il chiamante ha una sessione valida
Risposta
PUT mostra il 405 che Next.js invia per un metodo che il file non esporta.