Validazione e gestione degli errori
Prerequisiti: lezioni 19–22 e 25. Definisci un contratto verificabile anche quando il client sbaglia.
Dal formato al significato
- Parsing
- Trasforma il testo JSON in valori JavaScript; può fallire prima della route se il testo è malformato.
- Validazione
- Verifica forma, tipi, intervalli e regole del dato. La stringa vuota e un array sono JSON validi ma possono essere input non ammessi.
- Normalizzazione
- Converte input accettati in una forma uniforme, come un nome senza spazi esterni. Va documentata: non deve nascondere errori o trasformare qualunque valore in una stringa.
- Errore atteso e inatteso
- Un errore atteso, come un campo assente, può essere spiegato al client. Un errore inatteso richiede un log interno e una risposta che non esponga stack, credenziali o dettagli del filesystem.
Una funzione indipendente da Express
Salva come persona.mjs. È riutilizzata nella prossima lezione.
export function validaPersona(body) {
if (!body || typeof body !== 'object' || Array.isArray(body)) {
return { ok: false, error: 'È richiesto un oggetto' };
}
if (typeof body.nome !== 'string' ||
body.nome.trim().length === 0 || body.nome.trim().length > 80) {
return { ok: false, error: 'nome: da 1 a 80 caratteri' };
}
if (!Number.isInteger(body.eta) || body.eta < 0 || body.eta > 130) {
return { ok: false, error: 'eta: intero da 0 a 130' };
}
return { ok: true, value: { nome: body.nome.trim(), eta: body.eta } };
}La funzione non modifica il body e seleziona esplicitamente i campi ammessi. eta: "18" viene rifiutato: il contratto richiede un numero JSON. La lunghezza delle stringhe JavaScript misura unità UTF-16, non sempre caratteri percepiti dall’utente; chiarisci il requisito se gestisci nomi internazionali.
Collegarla a Express 5
In una cartella di esercizio esegui npm init -y e npm install express@5. Salva questo file come server.mjs accanto a persona.mjs; avvia con node server.mjs.
import express from 'express';
import { randomUUID } from 'node:crypto';
import { validaPersona } from './persona.mjs';
const app = express();
app.use(express.json({ limit: '16kb' }));
app.post('/persone', (req, res) => {
const esito = validaPersona(req.body);
if (!esito.ok) return res.status(400).json({ error: esito.error });
// Dimostrazione del contratto: non salva ancora la persona.
return res.status(201).json({ id: randomUUID(), ...esito.value });
});
app.use((req, res) => res.status(404).json({ error: 'Route assente' }));
app.use((err, req, res, next) => {
if (res.headersSent) return next(err);
if (err.type === 'entity.parse.failed') {
return res.status(400).json({ error: 'JSON malformato' });
}
if (err.type === 'entity.too.large') {
return res.status(413).json({ error: 'Body troppo grande' });
}
console.error(err);
return res.status(500).json({ error: 'Errore interno' });
});
app.listen(3000, '127.0.0.1');Matrice di verifica
| Body di POST /persone | Risposta attesa |
|---|---|
| {"nome":" Ada ","eta":20} | 201, nome normalizzato Ada e ID presente |
| {"nome":" ","eta":20} | 400 |
| null oppure [] | 400 |
| {"nome":"Ada","eta":"20"} | 400 |
| JSON incompleto | 400, JSON malformato |
Invia Content-Type: application/json. Interrompi il server con Ctrl+C dopo le prove. La validazione non sostituisce autenticazione e autorizzazione.
Per i gestori asincroni, Express 5 propaga il rifiuto delle Promise restituite; callback esterne richiedono inoltro esplicito. Documentazione Express sugli errori.