Lendo o corpo
Parte da seção Fundamentos de Express do Journey de Node.js da Coddy. Lição 15 de 23.
Uma requisição POST envia dados no corpo, e o Express não lê o corpo a menos que você peça.
app.use(express.json());
app.post('/api/loans', (req, res) => {
const { bookId, member } = req.body;
res.status(201).json({ bookId, member, due: '2026-11-08' });
});GET solicita algo; POST envia algo para ser criado. express.json() é um middleware que lê todos os corpos JSON em req.body. Sem ele, req.body é undefined. Uma rota que cria algo responde com o código 201 e aquilo que criou.
Verifique o corpo antes de salvá-lo. A ausência de um campo é um erro do cliente, então responda com o código 400 e não salve nada.
Desafio
FácilOs visitantes podem adicionar as próprias receitas. Um programa envia a nova receita como JSON no corpo de uma solicitação POST, e sua API a salva.
- Em
server.js, adicioneexpress.json()junto com as outras linhasapp.use, acima das rotas, para que um corpo JSON chegue emreq.body. - Adicione uma rota para solicitações POST a
/api/recipes. Ela lêtitleetagsdo corpo, por exemplo{"title": "Miso Soup", "tags": ["vegan", "soup"]}. - Ela cria a nova receita com o próximo número de id: as quatro receitas têm ids de 1 a 4, então a primeira nova receita recebe 5. Ela mantém o título e as tags recebidos. Se não vier
tags, use uma lista vazia,[]. - Ela adiciona a receita ao array
recipes, para queGET /api/recipesa liste. Em seguida, responde com o status 201 e a nova receita como JSON:{"id": 5, "title": "Miso Soup", "tags": ["vegan", "soup"]} - Quando o corpo não tem
title, ela não salva nada e responde com o status 400 e este JSON:{"error": "A recipe needs a title"}
Experimente: Pressione Executar. Escolha POST no seletor de método, digite /api/recipes como caminho e coloque {"title": "Miso Soup", "tags": ["vegan", "soup"]} na caixa do corpo. Você deverá ver o status 201 e a receita com "id": 5. Escolha GET e envie /api/recipes: cinco receitas, com Miso Soup por último. Depois, envie POST {"tags": ["dinner"]} para /api/recipes: status 400 e {"error":"A recipe needs a title"}. GET /api/recipes ainda lista cinco receitas.
Experimente você mesmo
import { escapeHtml } from './html.js';
import express from 'express';
import { randomUUID } from 'node:crypto';
import { recipes } from './data.js';
const app = express();
app.use((req, res, next) => {
console.log(`${req.method} ${req.url}`);
next();
});
app.use((req, res, next) => {
res.set('X-Request-Id', randomUUID());
next();
});
app.use(express.static('public'));
app.get('/', (req, res) => {
const items = recipes.map((r) => `<li><a href="/recipes/${r.id}">${escapeHtml(r.title)}</a></li>`);
res.send(`<link rel="stylesheet" href="/style.css"><h1>Recipe Box</h1><ul>${items.join('')}</ul>`);
});
// type('text') envia texto simples, então cada título aparece em sua própria linha.
app.get('/recipes', (req, res) => {
const { tag } = req.query;
const list = tag ? recipes.filter((recipe) => recipe.tags.includes(tag)) : recipes;
res.type('text').send(list.map((recipe) => recipe.title).join('\n'));
});
app.get('/recipes/:id', (req, res) => {
const recipe = recipes.find((r) => r.id === Number(req.params.id));
if (!recipe) {
res.status(404).send('No such recipe');
return;
}
res.send(recipe.title);
});
app.get('/api/recipes', (req, res) => {
res.json(recipes);
});
app.get('/api/recipes/:id', (req, res) => {
const recipe = recipes.find((r) => r.id === Number(req.params.id));
if (!recipe) {
res.status(404).json({ error: 'No such recipe' });
return;
}
res.json(recipe);
});
app.get('/about', (req, res) => {
res.send('Recipe Box collects family recipes.');
});
app.get('/menu', (req, res) => {
res.redirect(301, '/recipes');
});
app.get('/menu/:id', (req, res) => {
res.redirect(301, `/recipes/${req.params.id}`);
});
app.listen(3000, () => {
console.log('Recipe Box is running on port 3000');
});
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Fundamentos de Express
Pratique por conta própria: Playground de Express