Menu
CoddyTech

Tu primer middleware

Parte de la sección Conceptos básicos de Express del Journey de Node.js de Coddy. Lección 13 de 23.

Hay tareas que corresponden a todas las solicitudes, como escribir una línea en el registro, y copiarlas en cada ruta nunca terminaría. Cada solicitud tiene un método, en req.method: GET para obtener algo, POST para enviar algo.

let visits = 0;

app.use((req, res, next) => {
    visits++;
    next();
});

Una función que se pasa a app.use es un middleware: Express la ejecuta para cada solicitud, en el orden en que se añadió, antes de las rutas que aparecen debajo. Recibe un tercer argumento, next. Al llamar a next(), se pasa la solicitud a lo que venga a continuación. Un middleware que no responde ni llama a next() deja la solicitud esperando para siempre.

express.static, del capítulo anterior, también es middleware: responde cuando encuentra un archivo y llama a next() cuando no lo encuentra.

challenge icon

Desafío

Fácil

Quieres una línea de registro por cada solicitud que recibe tu servidor, para que puedas ver qué piden los visitantes.

  1. En server.js, justo después de const app = express();, añade un middleware con app.use. Al colocarlo ahí, se ejecuta antes de cada ruta.
  2. Para cada solicitud, imprime una línea en la consola: el método de la solicitud, un espacio y después su ruta. Una solicitud a /recipes/2 imprime GET /recipes/2. El método está en req.method (GET, POST, etc.) y la ruta está en req.url.
  3. Después de imprimir, llama a next(), para que la solicitud continúe hacia las rutas.

Pruébalo: Pulsa Ejecutar y envía /recipes/2. Deberías ver Pancakes, y la consola muestra GET /recipes/2. Envía /api/recipes: la lista como siempre, y GET /api/recipes en la consola. Envía /nope: un 404, y la consola sigue mostrando GET /nope, porque el middleware se ejecuta antes de que Express busque una ruta.

Pruébalo tú mismo

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

const app = express();

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') envía texto sin formato, por lo que cada título aparece en su propia línea.
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');
});
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Conceptos básicos de Express

Practica por tu cuenta: Playground de Express