Menu
CoddyTech

L'ordine conta

Fa parte della sezione Fondamenti di Express del percorso Node.js di Coddy. Lezione 14 di 23.

Express esegue il middleware e le route nell’ordine in cui il tuo codice le aggiunge, e una route che risponde conclude la richiesta.

app.get('/bikes', (req, res) => {
    res.json(bikes);
});

app.use((req, res, next) => {
    res.set('Cache-Control', 'no-store');
    next();
});

res.set(name, value) aggiunge un’intestazione alla risposta e deve essere eseguito prima che la risposta venga inviata. In questo caso, GET /bikes risponde prima che venga raggiunto il middleware, quindi la sua risposta non riceve mai l’intestazione: il middleware vede solo le richieste a cui nessuna route precedente ha risposto. Il middleware che deve intervenire su ogni risposta va inserito prima delle route e prima di express.static.

challenge icon

Sfida

Facile

Ogni risposta riceve un ID, così quando un visitatore segnala un problema puoi trovare la sua richiesta nel log. Ogni risposta ne ha bisogno: pagine, dati API e file inviati da public.

  1. In server.js, importa randomUUID da node:crypto. Ogni chiamata restituisce un nuovo ID casuale, come 3b241101-e2bb-4255-8caf-4136c566a962.
  2. Aggiungi un middleware che imposta un'intestazione della risposta chiamata X-Request-Id, contenente un nuovo randomUUID() per ogni richiesta, quindi chiama next().
  3. Posizionalo in modo che ogni richiesta lo attraversi, compresi i file inviati da express.static. Una risposta riceve l'intestazione solo se il middleware viene eseguito prima che qualcosa risponda.

Prova: premi «Esegui» e invia /api/recipes due volte. Nella scheda Headers, X-Request-Id ha un valore diverso ogni volta. Invia /style.css e /: anche ciascuna di queste risposte include X-Request-Id.

Provalo tu

import { escapeHtml } from './html.js';
import express from 'express';
import { recipes } from './data.js';

const app = express();

app.use((req, res, next) => {
    console.log(`${req.method} ${req.url}`);
    next();
});

app.use(express.static('public'));

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 semplice, quindi ogni titolo compare 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.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.listen(3000, () => {
    console.log('Recipe Box is running on port 3000');
});

Tutte le lezioni di Fondamenti di Express

Esercitati da solo: Playground Express