Menu
CoddyTech

Leer un cuerpo

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

Una solicitud POST envía datos en su cuerpo, y Express no lee el cuerpo a menos que se lo pidas.

app.use(express.json());

app.post('/api/loans', (req, res) => {
    const { bookId, member } = req.body;
    res.status(201).json({ bookId, member, due: '2026-11-08' });
});

GET solicita algo; POST envía algo para que se cree. express.json() es un middleware que lee todos los cuerpos JSON en req.body. Sin él, req.body es undefined. Una ruta que crea algo responde con el código 201 y lo que creó.

Comprueba el cuerpo antes de guardarlo. Si falta un campo, es un error del cliente, así que responde con el código 400 y no guardes nada.

challenge icon

Desafío

Fácil

Los visitantes pueden añadir sus propias recetas. Un programa envía la nueva receta como JSON en el cuerpo de una solicitud POST, y tu API la guarda.

  1. En server.js, añade express.json() junto con las otras líneas de app.use, antes de las rutas, para que el cuerpo JSON llegue a req.body.
  2. Añade una ruta para las solicitudes POST a /api/recipes. Lee title y tags del cuerpo; por ejemplo, {"title": "Miso Soup", "tags": ["vegan", "soup"]}.
  3. Construye la nueva receta con el siguiente número de id: las cuatro recetas tienen ids del 1 al 4, así que la primera nueva obtiene el 5. Conserva el título y las etiquetas que se enviaron. Si no se envió tags, usa una lista vacía, [].
  4. Añade la receta al arreglo recipes, para que GET /api/recipes la incluya en la lista. Después, responde con el estado 201 y la nueva receta como JSON: {"id": 5, "title": "Miso Soup", "tags": ["vegan", "soup"]}
  5. Cuando el cuerpo no tenga title, no guarda nada y responde con el estado 400 y este JSON: {"error": "A recipe needs a title"}

Pruébalo: Pulsa Ejecutar. Elige POST en el selector de método, escribe /api/recipes como ruta y coloca {"title": "Miso Soup", "tags": ["vegan", "soup"]} en el cuadro del cuerpo. Deberías ver el estado 201 y la receta con "id": 5. Elige GET y envía /api/recipes: habrá cinco recetas, con Miso Soup al final. Después, envía {"tags": ["dinner"]} mediante POST a /api/recipes: el estado será 400 y aparecerá {"error":"A recipe needs a title"}. GET /api/recipes seguirá mostrando cinco recetas.

Pruébalo tú mismo

import { escapeHtml } from './html.js';
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.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