¿Qué información traen los objetos `req` y `res` en Express y cuáles son los métodos de respuesta más comunes?
Ver respuesta — intenta responderla en voz alta primero
En cada handler (req, res), req (request) representa lo que envía el cliente y res (response) es lo que tú le devuelves. De req lees method, url, params, query, body y headers. Con res respondes usando métodos como res.json() (envía JSON), res.send() (envía texto/HTML/JSON), res.status() (fija el código HTTP) y res.end() (cierra sin cuerpo). res.status() devuelve el mismo res, así que puedes encadenar: res.status(201).json(...).
El objeto req contiene todo lo que llegó del cliente:
req.method: el verbo HTTP,"GET","POST", etc.req.url: la URL pedida, incluyendo el query string.req.params: los route params de la URL (/usuarios/:id→req.params.id).req.query: lo que viene después del?(?page=2→req.query.page).req.body: el cuerpo enviado (JSON del POST/PUT). Necesitaexpress.json().req.headers: las cabeceras (req.headers["content-type"], etc.).
El objeto res sirve para construir la respuesta. Métodos clave:
res.json(obj): envíaobjcomo JSON y pone elContent-Typecorrecto.res.send(algo): envía texto, HTML o incluso un objeto (lo convierte a JSON).res.status(codigo): fija el código de estado (200, 201, 404, 500...). No envía nada por sí solo, solo prepara el código; devuelverespara encadenar.res.end(): termina la respuesta sin cuerpo (útil para un204 No Content).
Regla de oro: por cada petición debes responder una sola vez. Enviar dos respuestas (por ejemplo un res.json y luego otro) tira un error.
const express = require("express");
const app = express();
// Necesario para poder leer req.body en formato JSON
app.use(express.json());
// Muestra la info que trae req
app.get("/inspeccionar/:id", (req, res) => {
// Leemos varias piezas del request
const info = {
metodo: req.method, // "GET"
url: req.url, // "/inspeccionar/7?debug=true"
parametro: req.params.id, // "7" (de la ruta :id)
query: req.query, // { debug: "true" } (después del ?)
userAgent: req.headers["user-agent"], // cabecera enviada por el cliente
};
// res.json envía el objeto como JSON con status 200 por defecto
res.json(info);
});
// Ejemplo de encadenamiento: fijar status y enviar JSON en una línea
app.post("/usuarios", (req, res) => {
const nuevo = { id: 1, nombre: req.body.nombre };
// status(201) prepara el código y devuelve res; json envía el cuerpo
res.status(201).json(nuevo);
});
// res.send con texto plano
app.get("/saludo", (req, res) => {
res.send("Hola mundo"); // Content-Type: text/html automático
});
// res.status + res.end: responder sin cuerpo (204 = sin contenido)
app.delete("/usuarios/:id", (req, res) => {
// ...aquí borrarías el usuario...
res.status(204).end();
});
app.listen(3000, () => {
console.log("Servidor en http://localhost:3000");
});
Probando con curl:
# Pasamos un route param (7) y un query (?debug=true)
curl "http://localhost:3000/inspeccionar/7?debug=true"
# POST con body JSON; deberías recibir 201 y el usuario creado
curl -X POST http://localhost:3000/usuarios \
-H "Content-Type: application/json" \
-d '{"nombre":"Ana"}'
Creer que res.status(404) por sí solo envía la respuesta. No es así: res.status() solo fija el código y devuelve res; tienes que encadenar un método que sí envíe cuerpo, como res.status(404).json({ error: "No encontrado" }) o res.status(404).end(). Si solo llamas res.status(404), la petición se queda colgada porque nunca se cerró. Otro error es responder dos veces (res.json(...) y después otro res.send(...)), lo que lanza "Cannot set headers after they are sent".
"En cada handler tengo
reqyres.reqes lo que manda el cliente: de ahí leomethod,url,paramspara los segmentos de la ruta,querypara lo que viene tras el?,bodypara el cuerpo yheaderspara las cabeceras.reses lo que devuelvo: usores.jsonpara mandar JSON,res.sendpara texto o HTML,res.statuspara fijar el código yres.endpara cerrar sin cuerpo. Algo clave:res.statusno envía nada solo, solo fija el código y devuelveres, por eso encadenores.status(201).json(...). Y siempre respondo una sola vez por petición, porque enviar dos respuestas tira el error de headers ya enviados."
¿Qué problema tiene este handler y cómo lo arreglas?
app.get("/usuarios/:id", (req, res) => {
const usuario = buscarUsuario(req.params.id);
if (!usuario) {
res.status(404);
}
res.json(usuario);
});
Ver respuesta
res.status(404) no envía respuesta, solo fija el código; el flujo continúa y llega a res.json(usuario), que enviará undefined como JSON... con status 200, no 404. La condición no cortó nada.
Se arregla enviando el cuerpo dentro del if y frenando la función con return:
app.get("/usuarios/:id", (req, res) => {
const usuario = buscarUsuario(req.params.id);
if (!usuario) {
return res.status(404).json({ error: "Usuario no encontrado" });
}
res.json(usuario);
});
El return evita que se ejecute el res.json de abajo y que se intente responder dos veces.