← Node & Express

Fundamentos de Express

¿Cuál es la diferencia entre `req.params`, `req.query` y `req.body` en Express?

Ver respuesta — intenta responderla en voz alta primero

Los tres traen datos del cliente, pero de lugares distintos de la petición:

  • req.params: los segmentos dinámicos de la ruta, definidos con : (por ejemplo /usuarios/:idreq.params.id).
  • req.query: lo que viene después del ? en la URL (por ejemplo ?page=2req.query.page).
  • req.body: el cuerpo de la petición (el JSON de un POST o PUT). Necesita que actives app.use(express.json()); si no, req.body es undefined.

Piensa en una URL como /usuarios/42?page=2 con un cuerpo JSON:

  • req.params → la parte dentro de la ruta. Sirve para identificar qué recurso quieres: el usuario 42. Se define en el path con :, como /usuarios/:id. Llega siempre como string.
  • req.query → la parte después del ?. Sirve para opciones o filtros: paginación, orden, búsqueda... ?page=2&orden=nombre da { page: "2", orden: "nombre" }. También llega como string.
  • req.bodyno va en la URL, viaja en el cuerpo de la petición. Sirve para enviar datos grandes o sensibles: el objeto que quieres crear o actualizar. Es lo típico en POST y PUT.

Punto crítico del body: Express no lee el body por sí solo. Necesitas un middleware que lo parsee. Para JSON es app.use(express.json()). Sin esa línea, req.body será undefined aunque el cliente sí haya enviado datos.

Resumen mental:

  • params = qué recurso (va en la ruta).
  • query = cómo lo quieres (va tras el ?).
  • body = qué datos mandas (va en el cuerpo, requiere express.json()).
const express = require("express");
const app = express();

// ¡IMPRESCINDIBLE para leer req.body como JSON!
// Sin esta línea, req.body sería undefined.
app.use(express.json());

// Ruta que usa los TRES a la vez:
//   /usuarios/:id       -> req.params.id
//   ?notificar=true     -> req.query.notificar
//   cuerpo JSON          -> req.body
app.put("/usuarios/:id", (req, res) => {
  const id = req.params.id;              // segmento de la ruta (string)
  const notificar = req.query.notificar; // opción tras el ? (string)
  const datos = req.body;                // cuerpo JSON enviado

  res.json({
    mensaje: `Actualizando usuario ${id}`,
    notificar: notificar,   // "true" (string, no booleano)
    datosRecibidos: datos,  // { nombre: "Ana Actualizada" }
  });
});

// Ejemplo de qué pasa SIN express.json() (para entender el error típico)
app.post("/sin-parser", (req, res) => {
  // Si arriba NO tuvieras app.use(express.json()),
  // req.body aquí sería undefined y esto reventaría al leer .nombre
  res.json({ recibido: req.body });
});

app.listen(3000, () => {
  console.log("Servidor en http://localhost:3000");
});

Probando con curl la ruta que usa los tres:

# id=42 (params), notificar=true (query), y un body JSON con el nombre
curl -X PUT "http://localhost:3000/usuarios/42?notificar=true" \
  -H "Content-Type: application/json" \
  -d '{"nombre":"Ana Actualizada"}'

# Respuesta esperada:
# {
#   "mensaje": "Actualizando usuario 42",
#   "notificar": "true",
#   "datosRecibidos": { "nombre": "Ana Actualizada" }
# }

Olvidar app.use(express.json()) y luego preguntarse por qué req.body sale undefined. Este es probablemente el error número uno de los juniors con Express: envías un POST con JSON, intentas leer req.body.nombre y el servidor explota con "Cannot read properties of undefined". El problema no es tu ruta, es que falta el middleware que parsea el body. Otro descuido relacionado: no mandar el header Content-Type: application/json en la petición, porque express.json() solo parsea cuerpos marcados como JSON.

"Los tres traen datos del cliente pero de sitios distintos. req.params son los segmentos dinámicos de la ruta, los que defino con dos puntos, como /usuarios/:id; sirven para identificar el recurso. req.query es lo que viene después del ?, como ?page=2; lo uso para filtros y opciones. Y req.body es el cuerpo de la petición, el JSON que mando en un POST o PUT. Lo importante del body es que Express no lo lee solo: necesito app.use(express.json()), y si me olvido de esa línea req.body sale undefined. Además, params y query siempre llegan como string, así que si necesito un número lo convierto."

Reto rápido

Tienes esta ruta y haces un POST con -d '{"nombre":"Ana"}', pero en la consola req.body sale undefined. ¿Qué falta?

const express = require("express");
const app = express();

app.post("/usuarios", (req, res) => {
  console.log(req.body); // undefined
  res.json({ creado: req.body });
});

app.listen(3000);
Ver respuesta

Falta registrar el middleware que parsea el JSON del cuerpo. Hay que añadir antes de las rutas:

app.use(express.json());

Express no lee el body por defecto; express.json() es quien lo interpreta y llena req.body. Sin él, req.body queda undefined aunque el cliente sí haya enviado datos. (También hay que asegurarse de enviar la petición con el header Content-Type: application/json, porque express.json() solo parsea cuerpos marcados como JSON.)