Menu
CoddyTech

Reemplazar con PUT

Parte de la sección API REST del Journey de Node.js de Coddy. Lección 5 de 25.

Un formulario de edición envía la tarea completa, todos los campos a la vez. PUT significa «reemplazar el recurso por esto», así que el cuerpo debe estar completo.

PATCH /api/invoices/7  { "paid": true }               → paid changes
PUT   /api/invoices/7  { "amount": 90, "paid": true } → invoice 7 replaced
PUT   /api/invoices/7  { "paid": true }               → 400: amount missing

Un PUT al que le falta un campo devuelve 400: reemplazar con una factura incompleta haría que se perdiera el importe. Los campos que pertenecen al servidor, como el id y la fecha de creación, provienen de la versión anterior, nunca del cuerpo:

const { id, issuedAt } = invoices[index];
invoices[index] = { id, amount, paid, issuedAt };
challenge icon

Desafío

Fácil

Un formulario de edición envía toda la tarea de una vez. Añade una ruta PUT que reemplace una tarea por lo que envía el cliente.

  1. En routes/tasks.js, añade PUT /api/tasks/:id. El cuerpo debe contener ambos campos, por ejemplo { "title": "Book the big room", "done": true }.
  2. Reemplaza title y done de la tarea por los valores del cuerpo. Conserva su id y createdAt de la tarea almacenada; nunca los tomes del cuerpo. Responde con el estado 200 y la tarea completa:
    { "id": 2, "title": "Book the big room", "done": true, "createdAt": "2026-03-03T10:30:00.000Z" }
  3. Si al cuerpo le falta title o done, responde con el estado 400 y { "error": "PUT needs every field: title and done" }, y no cambies nada. Un campo solo falta si no está en el cuerpo: "done": false es un valor válido.
  4. Si ninguna tarea tiene ese id, responde con el estado 404 y { "error": "Task not found" }, como en las otras rutas.

Pruébalo: PUT /api/tasks/2 con { "title": "Book the big room", "done": true } devuelve 200 y la tarea de arriba. Después, PUT /api/tasks/2 con solo { "done": true } devuelve 400, y GET /api/tasks/2 sigue mostrando "Book the big room". PUT /api/tasks/99 con ambos campos devuelve 404.

Pruébalo tú mismo

import { Router } from 'express';
import { nextId, tasks } from '../store.js';

const router = Router();

router.get('/', (req, res) => {
    res.json(tasks);
});

router.get('/:id', (req, res) => {
    const task = tasks.find((t) => t.id === Number(req.params.id));
    if (!task) {
        return res.status(404).json({ error: 'Task not found' });
    }
    res.json(task);
});

router.post('/', (req, res) => {
    const { title } = req.body ?? {};
    if (!title) {
        return res.status(400).json({ error: 'title is required' });
    }
    const task = { id: nextId(), title, done: false, createdAt: new Date().toISOString() };
    tasks.push(task);
    res.status(201).location(`/api/tasks/${task.id}`).json(task);
});

router.patch('/:id', (req, res) => {
    const task = tasks.find((t) => t.id === Number(req.params.id));
    if (!task) {
        return res.status(404).json({ error: 'Task not found' });
    }
    const { title, done } = req.body ?? {};
    if (title !== undefined) task.title = title;
    if (done !== undefined) task.done = done;
    res.json(task);
});

router.delete('/:id', (req, res) => {
    const index = tasks.findIndex((t) => t.id === Number(req.params.id));
    if (index === -1) {
        return res.status(404).json({ error: 'Task not found' });
    }
    tasks.splice(index, 1);
    res.status(204).end();
});

export default router;
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 API REST

Practica por tu cuenta: Playground de Express