En Express, req.params contiene los valores de los segmentos con nombre de la ruta (/users/:id da req.params.id), req.query contiene el query string que va después del ? (/search?q=node da req.query.q), y req.body contiene los datos enviados en el body de la petición. req.params y req.query se rellenan en todas las peticiones, pero req.body sigue siendo undefined hasta que un parser como app.use(express.json()) lo lee. Los valores de params y query siempre son strings.
La primera petición responde {"params":{"userId":"7"},"query":{"sort":"new","limit":"2"}}. Fíjate en las comillas: 7 y 2 son strings, así que conviértelos con Number() antes de hacer cálculos o compararlos con números. Ahora cambia el método a POST, deja la ruta /users/7/posts y envía el body {"title": "Hello", "draft": true}: la respuesta es 201 con "body":{"title":"Hello","draft":true}, donde true es un booleano de verdad porque viene de JSON.
req.params vs req.query vs req.body
req.params | req.query | req.body | |
|---|---|---|---|
| Viene de | La ruta, /users/:id | El query string, ?sort=new | El body de la petición |
| URL o body de ejemplo | /users/7 | /users?sort=new | {"name": "Ada"} |
| Valor | { id: '7' } | { sort: 'new' } | { name: 'Ada' } |
| Tipos | Strings | Strings y arrays de strings | Lo que contenga el JSON |
| Necesita configuración | Un :name en la ruta | Nada | app.use(express.json()) |
| Uso típico | Qué recurso | Filtrar, ordenar, paginar | Datos para crear o actualizar |
Una ruta puede tener varios parámetros, y cada nombre se convierte en una clave de req.params: /teams/:teamId/members/:memberId da los dos ids. Un guion o un punto también los separan, así que /flights/:from-:to convierte /flights/LAX-SFO en { from: 'LAX', to: 'SFO' }.
req.query con claves repetidas y ausentes
Una clave que aparece dos veces se convierte en un array, y una clave que falta es undefined, así que dale un valor por defecto a las opciones:
La respuesta es {"page":1,"tags":["red","sale"],"raw":{"tag":["red","sale"]}}. Envía GET /products?tag=red&page=3 y tags sigue siendo un array, ["red"], porque [].concat() convierte en array tanto un string como un array. Express 5 parsea los query strings con el parser simple de Node, así que ?filter[size]=m da la clave "filter[size]", no un objeto anidado; Express 4 sí lo anidaba.
req.body necesita express.json()
Node entrega el body como un stream de bytes. express.json() lo lee, lo parsea y rellena req.body, pero solo cuando la petición lleva Content-Type: application/json. Los formularios HTML envían application/x-www-form-urlencoded, que necesita express.urlencoded().
Envía POST /signup con el body {"email": "ada@example.com"} y obtienes 201 con {"email":"ada@example.com","name":"anonymous"}. Envía un body vacío y obtienes 400. El ?? {} importa: sin él, desestructurar undefined lanza un TypeError en cualquier petición que no tenga body JSON. Para validar de verdad la forma y los tipos, usa una librería de esquemas como zod.
req.headers y req.get()
req.headers es un objeto con todos los headers de la petición, con los nombres en minúsculas. req.get(name) lee un header ignorando mayúsculas, así que req.get('Content-Type') y req.get('content-type') devuelven lo mismo. Otras propiedades que vas a usar:
path es /whoami y originalUrl es /whoami?debug=1. Añade el header Authorization: Bearer abc en la barra de petición y vuelve a enviarla: token pasa a ser "Bearer abc". Dentro de un router montado con app.use('/api', router), req.path pierde el prefijo /api mientras que req.originalUrl lo conserva (rutas en Express explica cómo se monta).
Errores comunes
Leer req.body en una petición GET. Los navegadores y la mayoría de los clientes no envían body con GET. Pon las opciones de un GET en el query string.
Comprobar un flag del query como truthy. ?admin=false da el string 'false', que es truthy, así que if (req.query.admin) pasa. Compara strings: req.query.admin === 'true'.
Enviar JSON sin el header. Un cliente que envía JSON como text/plain obtiene req.body === undefined. Pon Content-Type: application/json en el cliente.
Preguntas frecuentes
¿Cómo obtengo la IP del cliente en Express?
Lee req.ip. Detrás de un proxy o un balanceador de carga es la dirección del proxy hasta que pones app.set('trust proxy', 1), que hace que Express lea el header X-Forwarded-For.
¿Cómo obtengo la URL completa de una petición en Express?
req.originalUrl es la ruta más el query string tal como los envió el cliente. Construye la URL absoluta con `${req.protocol}://${req.get('host')}${req.originalUrl}`.
¿Cómo manejo la subida de archivos en Express?
Los archivos llegan como multipart/form-data, que express.json() y express.urlencoded() no parsean. Usa un paquete como multer, que pone los archivos en req.file o req.files y los demás campos en req.body.
¿Cómo leo una cookie de la petición?
El header en bruto está en req.get('cookie'). Para tener un objeto en req.cookies, instala el paquete cookie-parser y añade app.use(cookieParser()).