No Express, req.params guarda os valores dos segmentos nomeados no caminho da rota (/users/:id dá req.params.id), req.query guarda a query string depois do ? (/search?q=node dá req.query.q), e req.body guarda os dados enviados no body da requisição. req.params e req.query são preenchidos em toda requisição, mas req.body fica undefined até um body parser como app.use(express.json()) lê-lo. Os valores em params e query são sempre strings.
A primeira requisição responde {"params":{"userId":"7"},"query":{"sort":"new","limit":"2"}}. Repare nas aspas: 7 e 2 são strings, então converta com Number() antes de fazer contas ou comparar com números. Agora troque o método para POST, mantenha o caminho /users/7/posts e envie o body {"title": "Hello", "draft": true}: a resposta é 201 com "body":{"title":"Hello","draft":true}, em que true é um booleano de verdade porque veio do JSON.
req.params vs req.query vs req.body
req.params | req.query | req.body | |
|---|---|---|---|
| Vem de | O caminho, /users/:id | A query string, ?sort=new | O body da requisição |
| URL ou body de exemplo | /users/7 | /users?sort=new | {"name": "Ada"} |
| Valor | { id: '7' } | { sort: 'new' } | { name: 'Ada' } |
| Tipos | Strings | Strings e arrays de strings | O que o JSON tiver |
| Precisa de setup | Um :name na rota | Nada | app.use(express.json()) |
| Uso típico | Qual recurso | Filtrar, ordenar, paginar | Dados para criar ou atualizar |
Uma rota pode ter vários parâmetros, e cada nome vira uma chave de req.params: /teams/:teamId/members/:memberId dá os dois ids. Um hífen ou um ponto também os separa, então /flights/:from-:to transforma /flights/LAX-SFO em { from: 'LAX', to: 'SFO' }.
req.query com chaves repetidas e ausentes
Uma chave que aparece duas vezes vira um array, e uma chave ausente é undefined, então dê um valor padrão às opções:
A resposta é {"page":1,"tags":["red","sale"],"raw":{"tag":["red","sale"]}}. Envie GET /products?tag=red&page=3 e tags continua sendo array, ["red"], porque [].concat() transforma uma string ou um array em array. O Express 5 interpreta query strings com o parser simples do Node, então ?filter[size]=m dá a chave "filter[size]", não um objeto aninhado; o Express 4 aninhava.
req.body precisa de express.json()
O Node entrega o body como uma stream de bytes. express.json() lê, interpreta e define req.body, mas só quando a requisição tem Content-Type: application/json. Formulários HTML enviam application/x-www-form-urlencoded, que precisa de express.urlencoded().
Envie POST /signup com o body {"email": "ada@example.com"} e você recebe 201 com {"email":"ada@example.com","name":"anonymous"}. Envie um body vazio e você recebe 400. O ?? {} importa: sem ele, desestruturar undefined lança TypeError em qualquer requisição sem body JSON. Para validar de verdade a forma e os tipos, use uma biblioteca de schema como o zod.
req.headers e req.get()
req.headers é um objeto com todos os headers da requisição, com nomes em minúsculas. req.get(name) lê um header ignorando maiúsculas e minúsculas, então req.get('Content-Type') e req.get('content-type') retornam o mesmo valor. Algumas outras propriedades que você vai usar:
path é /whoami e originalUrl é /whoami?debug=1. Adicione o header Authorization: Bearer abc na barra de requisição e envie de novo: token vira "Bearer abc". Dentro de um router montado com app.use('/api', router), req.path perde o prefixo /api enquanto req.originalUrl o mantém (as rotas no Express explicam a montagem).
Erros comuns
Ler req.body em uma requisição GET. Navegadores e a maioria dos clientes não enviam body com GET. Coloque as opções de GET na query string.
Testar uma flag da query como truthy. ?admin=false dá a string 'false', que é truthy, então if (req.query.admin) passa. Compare strings: req.query.admin === 'true'.
Enviar JSON sem o header. Um cliente que envia JSON como text/plain recebe req.body === undefined. Defina Content-Type: application/json no cliente.
Perguntas frequentes
Como pego o IP do cliente no Express?
Leia req.ip. Atrás de um proxy ou load balancer ele é o endereço do proxy até você definir app.set('trust proxy', 1), que faz o Express ler o header X-Forwarded-For.
Como pego a URL completa de uma requisição no Express?
req.originalUrl é o caminho mais a query string, como o cliente enviou. Monte a URL absoluta com `${req.protocol}://${req.get('host')}${req.originalUrl}`.
Como trato upload de arquivos no Express?
Uploads de arquivo chegam como multipart/form-data, que express.json() e express.urlencoded() não interpretam. Use um pacote como o multer, que coloca os arquivos em req.file ou req.files e os outros campos em req.body.
Como leio um cookie da requisição?
O header cru está em req.get('cookie'). Para ter um objeto em req.cookies, instale o pacote cookie-parser e adicione app.use(cookieParser()).