O que você vai aprender
Ao estudar esta página, o foco é entender recurso, rota, requisição, resposta, JSON (JavaScript Object Notation), CRUD e a relação entre URL + método HTTP + status code.
- REST
- HTTP
- GET
- POST
- PUT
- DELETE
- Express
- JSON
Esta página apresenta os conceitos essenciais de REST, mostra como funcionam os verbos HTTP e os códigos de status, e constrói passo a passo uma API REST simples com Express usando dados em memória.
Ao estudar esta página, o foco é entender recurso, rota, requisição, resposta, JSON (JavaScript Object Notation), CRUD e a relação entre URL + método HTTP + status code.
REST é um estilo de organização para APIs no qual trabalhamos com recursos, como
/estudantes, /produtos ou /tarefas, e usamos os métodos do HTTP para dizer
o que queremos fazer com esses recursos.
Em vez de criar URLs como:
/buscarEstudantes
/criarEstudante
/removerEstudante
em REST preferimos URLs que representam o recurso:
/estudantes
/estudantes/1
/tarefas./tarefas/3.Os métodos HTTP indicam a intenção da requisição. Em APIs REST, os verbos mais usados são GET, POST, PUT e DELETE.
| Operação | Método | Exemplo de rota | Ideia principal |
|---|---|---|---|
| Create | POST | /tarefas |
Cria um novo item. |
| Read | GET | /tarefas ou /tarefas/1 |
Lê todos os itens ou um item específico. |
| Update | PUT | /tarefas/1 |
Atualiza um item existente. |
| Delete | DELETE | /tarefas/1 |
Remove um item. |
GET é usado para consultar dados. Ele não deve alterar o estado do recurso.
GET /tarefas
GET /tarefas/2
POST é usado para criar um novo recurso.
POST /tarefas
PUT é usado para atualizar um recurso existente.
PUT /tarefas/2
DELETE é usado para remover um recurso.
DELETE /tarefas/2
Os códigos de status mostram o resultado da requisição. Em APIs REST, é importante usar um código coerente com a operação realizada.
A requisição foi processada com sucesso.
Há problema na requisição enviada.
O servidor falhou ao processar a operação.
Devolver sempre 200, mesmo quando falta campo, quando o item não existe ou quando houve falha.
Usar 201 para criar, 400 para entrada inválida, 404 para item ausente e 204 para remoção sem corpo.
Uma API bem organizada não depende apenas do código funcionar; ela também precisa responder de forma clara e consistente.
Agora vamos montar uma API REST simples com Node.js e Express. O exemplo usará uma lista de tarefas armazenada em memória, isto é, os dados existem apenas enquanto o servidor está ligado.
npm init -y
npm install express
Crie um arquivo chamado server.js com a estrutura abaixo:
const express = require('express');
const app = express();
app.use(express.json());
const tarefas = [
{ id: 1, titulo: 'Estudar REST', concluida: false },
{ id: 2, titulo: 'Praticar Express', concluida: true }
];
app.get('/', (req, res) => {
res.send('API funcionando!');
});
app.listen(3000, () => {
console.log('Servidor rodando em http://localhost:3000');
});
express()app.use(express.json())app.listen(3000)node server.js
Se tudo estiver certo, ao acessar http://localhost:3000 você verá a mensagem
API funcionando!.
Agora vamos implementar as quatro operações principais sobre o recurso tarefas.
A coleção será /tarefas e o item individual será /tarefas/:id.
const express = require('express');
const app = express();
app.use(express.json());
let tarefas = [
{ id: 1, titulo: 'Estudar REST', concluida: false },
{ id: 2, titulo: 'Praticar Express', concluida: true }
];
let proximoId = 3;
app.get('/tarefas', (req, res) => {
res.status(200).json(tarefas);
});
app.get('/tarefas/:id', (req, res) => {
const id = Number(req.params.id);
const tarefa = tarefas.find(t => t.id === id);
if (!tarefa) {
return res.status(404).json({ erro: 'Tarefa não encontrada' });
}
res.status(200).json(tarefa);
});
app.post('/tarefas', (req, res) => {
const { titulo, concluida } = req.body;
if (!titulo || typeof titulo !== 'string') {
return res.status(400).json({ erro: 'O campo titulo é obrigatório' });
}
const novaTarefa = {
id: proximoId++,
titulo,
concluida: concluida ?? false
};
tarefas.push(novaTarefa);
res.status(201).json(novaTarefa);
});
app.put('/tarefas/:id', (req, res) => {
const id = Number(req.params.id);
const { titulo, concluida } = req.body;
const indice = tarefas.findIndex(t => t.id === id);
if (indice === -1) {
return res.status(404).json({ erro: 'Tarefa não encontrada' });
}
if (!titulo || typeof titulo !== 'string') {
return res.status(400).json({ erro: 'O campo titulo é obrigatório' });
}
tarefas[indice] = {
id,
titulo,
concluida: Boolean(concluida)
};
res.status(200).json(tarefas[indice]);
});
app.delete('/tarefas/:id', (req, res) => {
const id = Number(req.params.id);
const indice = tarefas.findIndex(t => t.id === id);
if (indice === -1) {
return res.status(404).json({ erro: 'Tarefa não encontrada' });
}
tarefas.splice(indice, 1);
res.status(204).send();
});
app.listen(3000, () => {
console.log('Servidor rodando em http://localhost:3000');
});
Retorna a lista completa de tarefas.
app.get('/tarefas', (req, res) => {
res.status(200).json(tarefas);
});
Palavras-chave: listar, coleção, leitura, 200 OK.
Busca uma tarefa específica pelo identificador enviado na URL.
app.get('/tarefas/:id', (req, res) => {
const id = Number(req.params.id);
const tarefa = tarefas.find(t => t.id === id);
if (!tarefa) {
return res.status(404).json({ erro: 'Tarefa não encontrada' });
}
res.status(200).json(tarefa);
});
Palavras-chave: parâmetro de rota, busca, item único, 404.
Recebe dados no corpo da requisição, valida o título e cria uma nova tarefa.
app.post('/tarefas', (req, res) => {
const { titulo, concluida } = req.body;
if (!titulo || typeof titulo !== 'string') {
return res.status(400).json({ erro: 'O campo titulo é obrigatório' });
}
const novaTarefa = {
id: proximoId++,
titulo,
concluida: concluida ?? false
};
tarefas.push(novaTarefa);
res.status(201).json(novaTarefa);
});
Palavras-chave: body, validação, criação, 201 Created.
Atualiza os dados de uma tarefa que já existe.
app.put('/tarefas/:id', (req, res) => {
const id = Number(req.params.id);
const { titulo, concluida } = req.body;
const indice = tarefas.findIndex(t => t.id === id);
if (indice === -1) {
return res.status(404).json({ erro: 'Tarefa não encontrada' });
}
if (!titulo || typeof titulo !== 'string') {
return res.status(400).json({ erro: 'O campo titulo é obrigatório' });
}
tarefas[indice] = {
id,
titulo,
concluida: Boolean(concluida)
};
res.status(200).json(tarefas[indice]);
});
Palavras-chave: atualização, id, validação, substituição, 200 OK.
Remove uma tarefa pelo id.
app.delete('/tarefas/:id', (req, res) => {
const id = Number(req.params.id);
const indice = tarefas.findIndex(t => t.id === id);
if (indice === -1) {
return res.status(404).json({ erro: 'Tarefa não encontrada' });
}
tarefas.splice(indice, 1);
res.status(204).send();
});
Palavras-chave: remoção, 204 No Content, item inexistente, 404.
Você pode testar com navegador, Postman, Insomnia ou VS Code REST Client. O importante é observar método, URL, body e status code.
node server.js.GET /tarefas para verificar a lista inicial.POST /tarefas para criar uma nova tarefa.GET /tarefas/:id para consultar o item criado.PUT /tarefas/:id para alterar os dados.DELETE /tarefas/:id para remover o item.404.GET http://localhost:3000/tarefas
POST http://localhost:3000/tarefas
Content-Type: application/json
{
"titulo": "Montar API REST",
"concluida": false
}
PUT http://localhost:3000/tarefas/1
Content-Type: application/json
{
"titulo": "Montar API REST com Express",
"concluida": true
}
DELETE http://localhost:3000/tarefas/1
Esse modelo é excelente para aprender o funcionamento das rotas REST, mas possui uma limitação importante: os dados ficam apenas na variável do programa.
Mesmo assim, esse é o melhor ponto de partida para compreender o comportamento de uma API antes de integrar banco, autenticação, camadas de serviço e tratamento de erros mais robusto.