Gestione degli errori
Fa parte della sezione Fondamenti di Express del percorso Node.js di Coddy. Lezione 15 di 20.
Quando una route genera un errore, Express risponde con la propria pagina di errore, che non è JSON e mostra dettagli destinati a te.
app.get('/api/fines/:member', (req, res) => {
throw new Error('Fines database is down');
});
app.use((err, req, res, next) => {
console.error(err);
res.status(500).json({ error: 'Try again later' });
});Un middleware con quattro argomenti, (err, req, res, next), è un gestore degli errori. Express conta gli argomenti: con tre è un middleware ordinario e gli errori lo ignorano. Quando una route genera un errore, Express ignora il middleware ordinario e chiama il gestore degli errori passandogli l'errore. Aggiungilo per ultimo, dopo il gestore 404. Registra i dettagli per te; invia al client un messaggio breve.
Un valore ?by= non valido è un errore del visitatore, quindi restituisce comunque un 400. Un errore riguarda qualcosa che il visitatore non può correggere, come una ricetta salvata senza il numero di porzioni.
Sfida
FacileGET /api/recipes/:id/scale?by=2restituisce{ "title", "servings" }, con le porzioni moltiplicate.- Un fattore che non è un numero positivo:
400con{ "error": "Scale by a positive number" }. - Una ricetta senza
servingsgeneraRecipe <id> has no servings. - Un gestore degli errori registra l'errore e restituisce
500con{ "error": "Something went wrong" }.
Invia ?by=2 e ?by=lots. Poi invia { "title": "Toast" } a /api/recipes e ridimensiona la ricetta 5.
Provalo tu
import express from 'express';
import { randomUUID } from 'node:crypto';
import { recipes } from './data.js';
const app = express();
app.use((req, res, next) => {
console.log(`${req.method} ${req.url}`);
next();
});
app.use((req, res, next) => {
res.set('X-Request-Id', randomUUID());
next();
});
app.use(express.json());
app.use(express.static('public'));
const escapeHtml = (text) =>
text
.replaceAll('&', '&')
.replaceAll('<', '<')
.replaceAll('>', '>')
.replaceAll('"', '"');
app.get('/', (req, res) => {
const items = recipes.map((r) => `<li><a href="/recipes/${r.id}">${escapeHtml(r.title)}</a></li>`);
res.send(`<link rel="stylesheet" href="/style.css"><h1>Recipe Box</h1><ul>${items.join('')}</ul>`);
});
// type('text') invia testo normale, quindi ogni titolo appare su una riga a sé.
app.get('/recipes', (req, res) => {
const { tag } = req.query;
const list = tag ? recipes.filter((recipe) => recipe.tags.includes(tag)) : recipes;
res.type('text').send(list.map((recipe) => recipe.title).join('\n'));
});
app.get('/recipes/:id', (req, res) => {
const recipe = recipes.find((r) => r.id === Number(req.params.id));
if (!recipe) {
res.status(404).send('No such recipe');
return;
}
res.send(recipe.title);
});
app.get('/api/recipes', (req, res) => {
res.json(recipes);
});
app.get('/api/recipes/:id', (req, res) => {
const recipe = recipes.find((r) => r.id === Number(req.params.id));
if (!recipe) {
res.status(404).json({ error: 'No such recipe' });
return;
}
res.json(recipe);
});
app.post('/api/recipes', (req, res) => {
const { title, tags } = req.body;
if (!title) {
res.status(400).json({ error: 'A recipe needs a title' });
return;
}
const recipe = { id: recipes.length + 1, title, tags: tags ?? [] };
recipes.push(recipe);
res.status(201).json(recipe);
});
app.get('/about', (req, res) => {
res.send('Recipe Box collects family recipes.');
});
app.get('/menu', (req, res) => {
res.redirect(301, '/recipes');
});
app.get('/menu/:id', (req, res) => {
res.redirect(301, `/recipes/${req.params.id}`);
});
app.use((req, res) => {
if (req.path.startsWith('/api/')) {
res.status(404).json({ error: 'Not found' });
return;
}
res.status(404).send('<h1>Page not found</h1><p><a href="/">Back to Recipe Box</a></p>');
});
app.listen(3000, () => {
console.log('Recipe Box is running on port 3000');
});
Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.
Tutte le lezioni di Fondamenti di Express
3Middleware
Il tuo primo middleware