Node.js: Design de API REST

Última atualização: 2026-08-26

A equipe da Alice está desenvolvendo tanto o front-end quanto o back-end de um sistema de gerenciamento de tarefas. Os desenvolvedores de front-end estão reclamando que não sabem quais APIs estão disponíveis, quais métodos HTTP devem usar nem em quais formatos as respostas serão fornecidas. Os desenvolvedores de back-end estão igualmente frustrados — para a mesma operação de “atualização de tarefa”, alguns usam POST, outros usam PUT e outros ainda usam PATCH, resultando em uma grande variedade de formatos de resposta. A colaboração se transformou em caos.

Alice decidiu adotar a especificação REST. Depois que a equipe padronizou a nomenclatura dos recursos, o mapeamento de métodos, os códigos de status e os formatos de resposta, a API tornou-se clara e previsível; a equipe de front-end não precisou mais consultar repetidamente a documentação da API, e a eficiência da colaboração dobrou.

1. O que você vai aprender



2. Princípios da arquitetura REST

(1) O que é REST?

REST (Representational State Transfer) é um estilo de arquitetura de software proposto por Roy Fielding em 2000. Ele define um conjunto de restrições para o projeto de interfaces de aplicativos da web. O REST não é um protocolo nem um padrão, mas sim uma filosofia de projeto.

(2) Quatro princípios fundamentais

Princípio Significado Exemplo
Recurso Tudo é um recurso, identificado por uma URL /tasks, /users/42
Camada de representação O formato no qual um recurso é representado, como JSON {"id": 1, "タイトル": "Learn REST"}
Sem estado Cada solicitação contém todas as informações necessárias As solicitações incluem um token e não dependem de sessões
Interface padronizada Operar recursos usando métodos HTTP padrão GET para ler, POST para criar, DELETE para excluir

▶ Exemplo: Sem estado vs. Com estado

JAVASCRIPT
// Stateful: Depends on server session (not RESTful)
app.post('/login', (req, res) => {
  req.session.userId = 42; // Server State Saving
  res.send('logged in');
});

app.get('/profile', (req, res) => {
  const userId = req.session.userId; // Depends on the server status
  res.json({ id: userId, name: 'Alice' });
});

// Stateless:Include authentication information with every request(RESTful)
app.get('/profile', (req, res) => {
  const userId = verifyToken(req.headers.authorization);
  res.json({ id: userId, name: 'Alice' });
});
▶ Experimente

3. CRUD e mapeamentos de métodos HTTP

(1) Relação de mapeamento padrão

A ideia central do REST é usar métodos HTTP para expressar a intenção das operações sobre os recursos, em vez de incorporar verbos de ação nas URLs.

Operações CRUD Métodos HTTP Caminhos Idempotência Segurança
Criar POST /tasks Não Não
Ler (Lista) GET /tasks Sim Sim
Leitura (única) GET /tasks/42 Sim Sim
Atualização (Completa) PUT /tasks/42 Sim Não
Atualização (parcial) PATCH /tasks/42 Não Não
Excluir EXCLUIR /tasks/42 Sim Não

(2) Uma explicação detalhada sobre a idempotência

Idempotência significa que executar a mesma solicitação uma vez tem o mesmo efeito que executá-la várias vezes. GET, PUT e DELETE são idempotentes, enquanto POST e PATCH não são.

▶ Exemplo: Diferenças na idempotência entre PUT e POST

JAVASCRIPT
// POST: Creates a new resource on every call (Non-idempotent)
// 1st POST /tasks → Create id=1
// 2nd POST /tasks → Create id=2
app.post('/tasks', (req, res) => {
  const task = { id: nextId++, ...req.body };
  tasks.push(task);
  res.status(201).json(task);
});

// PUT: Replaces the same resource on every call (Idempotent)
// 1st PUT /tasks/1 → Replace id=1
// 2nd PUT /tasks/1 → Replace id=1 (The results are the same)
app.put('/tasks/:id', (req, res) => {
  const idx = tasks.findIndex(t => t.id === parseInt(req.params.id));
  if (idx === -1) return res.status(404).json({ error: 'Not found' });
  tasks[idx] = { id: parseInt(req.params.id), ...req.body };
  res.json(tasks[idx]);
});
▶ Experimente

▶ Exemplo: Atualização parcial com PATCH

JAVASCRIPT
// PATCH:Modify only the fields provided
app.patch('/tasks/:id', (req, res) => {
  const task = tasks.find(t => t.id === parseInt(req.params.id));
  if (!task) return res.status(404).json({ error: 'Not found' });
  Object.assign(task, req.body);
  res.json(task);
});

// Request:Modify only status Field
// PATCH /tasks/1  {"status": "done"}
// Raw Data:{"id":1,"title":"Learn REST","status":"pending"}
// Results:{"id":1,"title":"Learn REST","status":"done"}
▶ Experimente

4. Diretrizes para a criação de URLs

(1) Regras básicas

O projeto de URLs RESTful segue um conjunto de convenções que tornam as APIs intuitivas e fáceis de ler.

Regra Correto ✅ Incorreto ❌
Use substantivos, não verbos GET /tasks GET /getTasks
Use o plural, não o singular /tasks /task
Representação de relações por meio de aninhamento /users/42/tasks /tasksByUser?userId=42
No máximo 3 níveis /users/42/tasks/1 /orgs/1/teams/2/users/42/tasks
Filtrar por parâmetros de consulta /tasks?status=done /doneTasks
Usando o kebab-case /task-アイテム /taskItems

(2) Projeto de recursos aninhados

Recursos aninhados indicam uma relação hierárquica. Use caminhos aninhados quando um recurso filho não puder existir independentemente de seu recurso pai.

▶ Exemplo: Estrutura de URLs para um sistema de gerenciamento de tarefas

TEXT 📖 Somente leitura
# Mission Resources
GET    /tasks              # Get the task list
POST   /tasks              # Create a New Task
GET    /tasks/42           # Get a Single Task
PUT    /tasks/42           # Full Update Task
PATCH  /tasks/42           # Partial Update Task
DELETE /tasks/42           # Delete Task

# Comments on the Assignment(Nested Resources)
GET    /tasks/42/comments           # Get a Task42List of comments
POST   /tasks/42/comments           # For the mission42Add a comment
GET    /tasks/42/comments/7         # Get a Task42Comments on7
DELETE /tasks/42/comments/7         # Delete Comment7

# Filtering and Pagination
GET    /tasks?status=done&page=2&limit=20
GET    /tasks?sort=-created_at      # Sort by creation date in reverse chronological order

▶ Exemplo: Usos comuns dos parâmetros de consulta em URLs

JAVASCRIPT
app.get('/tasks', (req, res) => {
  let result = [...tasks];

  // Filter
  if (req.query.status) {
    result = result.filter(t => t.status === req.query.status);
  }

  // Sort
  if (req.query.sort) {
    const field = req.query.sort.startsWith('-')
      ? req.query.sort.slice(1)
      : req.query.sort;
    const order = req.query.sort.startsWith('-') ? -1 : 1;
    result.sort((a, b) => (a[field] > b[field] ? order : -order));
  }

  // Pagination
  const page = parseInt(req.query.page) || 1;
  const limit = parseInt(req.query.limit) || 20;
  const start = (page - 1) * limit;
  result = result.slice(start, start + limit);

  res.json({
    data: result,
    page,
    limit,
    total: tasks.length
  });
});
▶ Experimente

5. Escolha dos códigos de status HTTP

(1) Classificação e seleção de códigos de status

Os códigos de status HTTP são sinais essenciais para a comunicação entre APIs REST e clientes. Ao escolher o código de status correto, os clientes podem compreender com precisão o resultado de uma solicitação.

Cenário Código de status Significado Descrição
Recurso recuperado com sucesso 200 OK Solicitação bem-sucedida Retornado quando GET/PUT/PATCH é bem-sucedido
Recurso criado com sucesso 201 Criado Recurso criado Retornado após uma solicitação POST bem-sucedida; deve incluir um cabeçalho Location
Recurso excluído com sucesso 204 Sem conteúdo Sem conteúdo Retornado quando a operação DELETE é bem-sucedida; sem corpo de resposta
Parâmetros de solicitação inválidos 400 Solicitação inválida Erro de sintaxe na solicitação do cliente Campos obrigatórios ausentes, formato inválido
Não autenticado 401 Não autorizado Nenhuma informação de autenticação fornecida Token ausente ou inválido
Sem permissão 403 Proibido Autenticado, mas sem permissão Usuário comum acessando a interface de administração
O recurso não existe 404 Não encontrado O recurso solicitado não existe O recurso com este ID não foi encontrado
Erro do servidor 500 Erro interno do servidor Erro interno do servidor Exceção não capturada

(2) Erros comuns: uso incorreto dos códigos de status

▶ Exemplo: Uso correto dos códigos de status

JAVASCRIPT
// Create a Resource → 201 + Location
app.post('/tasks', (req, res) => {
  const task = { id: nextId++, ...req.body };
  tasks.push(task);
  res.status(201)
     .location(`/tasks/${task.id}`)
     .json(task);
});

// Delete Resource → 204(Non-responsive body)
app.delete('/tasks/:id', (req, res) => {
  const idx = tasks.findIndex(t => t.id === parseInt(req.params.id));
  if (idx === -1) return res.status(404).json({ error: 'Not found' });
  tasks.splice(idx, 1);
  res.status(204).end();
});

// Verification Failed → 400 + Error Details
app.post('/tasks', (req, res) => {
  if (!req.body.title) {
    return res.status(400).json({
      error: 'Validation failed',
      details: [{ field: 'title', message: 'Title is required' }]
    });
  }
  // ...
});
▶ Experimente

6. Formatos de solicitação e resposta

(1) Convenções da especificação JSON

Convenção Padrão Exemplo
Nome do campo camelCase createdAt, taskId
Formato de data ISO 8601 2025-07-03T10:30:00Z
Resposta da lista Inclui dados + informações de paginação {"data": [...], "total": 100}
Resposta de erro Inclui o erro + detalhes {"error": "Not found", "details": [...]}
Tratamento de valores nulos Use null em vez de omitir o campo {"description": null}
Tipo de ID String (para evitar problemas de precisão) {"id": "42"}

▶ Exemplo: Resposta com lista padronizada

JAVASCRIPT
app.get('/tasks', (req, res) => {
  const page = parseInt(req.query.page) || 1;
  const limit = parseInt(req.query.limit) || 20;
  const start = (page - 1) * limit;
  const data = tasks.slice(start, start + limit);

  res.json({
    data,
    pagination: {
      page,
      limit,
      total: tasks.length,
      totalPages: Math.ceil(tasks.length / limit)
    }
  });
});
▶ Experimente
TEXT 📖 Somente leitura
// Response Example
{
  "data": [
    {
      "id": "1",
      "タイトル": "Learn REST",
      "status": "pending",
      "createdAt": "2025-07-03T10:30:00Z"
    }
  ],
  "pagination": {
    "page": 1,
    "limit": 20,
    "total": 1,
    "totalPages": 1
  }
}

▶ Exemplo: Resposta de erro padronizada

JAVASCRIPT
// Unified Error Handling Middleware
app.use((err, req, res, next) => {
  console.error(err.stack);
  res.status(err.status || 500).json({
    error: err.message || 'Internal Server Error',
    details: err.details || [],
    requestId: req.id,
    timestamp: new Date().toISOString()
  });
});

// Custom Error Classes
class ApiError extends Error {
  constructor(status, message, details = []) {
    super(message);
    this.status = status;
    this.details = details;
  }
}

// Usage
app.get('/tasks/:id', (req, res, next) => {
  const task = tasks.find(t => t.id === parseInt(req.params.id));
  if (!task) {
    return next(new ApiError(404, 'Task not found', [
      { field: 'id', message: `No task with id ${req.params.id}` }
    ]));
  }
  res.json(task);
});
▶ Experimente
TEXT 📖 Somente leitura
// Examples of Error Responses
{
  "error": "Task not found",
  "details": [
    { "field": "id", "message": "No task with id 999" }
  ],
  "requestId": "req-a1b2c3",
  "timestamp": "2025-07-03T10:30:00Z"
}


7. Estratégia de versionamento da API

(1) Comparação entre três estratégias predominantes

Estratégia Exemplo Vantagens Desvantagens Cenários aplicáveis
Caminho da URL /api/v1/tasks Intuitivo, pode ser testado em um navegador URLs mais longas, o que gera polêmica entre os defensores puristas do REST A maioria das APIs públicas
Cabeçalho da solicitação Accept: application/vnd.myapi.v1+json URL RESTful limpa e pura Não é intuitiva, difícil de depurar Busca a pureza REST
Parâmetro de consulta /api/tasks?version=1 Mais simples Facilmente ignorado; estratégia de cache complexa APIs internas, projetos simples

(2) Melhores práticas para controle de versões

▶ Exemplo: Implementação do controle de versão de caminhos de URL

JAVASCRIPT
// Routing Structure
// /api/v1/tasks → v1 Logic
// /api/v2/tasks → v2 Logic

const express = require('express');
const app = express();

// v1 Routing
const v1Router = express.Router();
v1Router.get('/tasks', (req, res) => {
  res.json({ data: tasks, version: 'v1' }); // v1 Return Format
});

// v2 Routing(Response Format Upgrade)
const v2Router = express.Router();
v2Router.get('/tasks', (req, res) => {
  res.json({                        // v2 Return Format(Includes pagination)
    data: tasks,
    pagination: { page: 1, total: tasks.length }
  });
});

app.use('/api/v1', v1Router);
app.use('/api/v2', v2Router);

// Response Header Version
app.use('/api/v2', (req, res, next) => {
  res.setHeader('X-API-Version', '2.0');
  next();
});
▶ Experimente

8. Modelo de Maturidade REST

(1) O Modelo de Maturidade de Richardson

Leonard Richardson propôs um modelo para medir a maturidade RESTful de uma API:

100%
graph TD
    L0["Level 0: Single endpoint<br/>HTTP as a tunnel<br/>e.g. POST /api  {action: getTasks}"]
    L1["Level 1: Resource URLs<br/>One URL per resource<br/>e.g. POST /tasks, POST /users"]
    L2["Level 2: HTTP Methods<br/>GET/POST/PUT/DELETE<br/>e.g. GET /tasks, DELETE /tasks/1"]
    L3["Level 3: HATEOAS<br/>Responses contain hyperlinks<br/>e.g. Response includes next, self links"]
    L0 --> L1 --> L2 --> L3
    style L0 fill:#ff6b6b,color:#fff
    style L1 fill:#ffa502,color:#fff
    style L2 fill:#2ed573,color:#fff
    style L3 fill:#1e90ff,color:#fff
Nível Características Exemplo de solicitação Exemplo de resposta
Nível 0 Túnel HTTP, URL única POST /api {"action":"getTasks"} {"tasks": [...]}
Nível 1 Separação de resíduos; qualquer método permitido POST /tasks {"tasks": [...]}
Nível 2 HTTP semanticamente correto GET /tasks 200 {"data": [...]}
Nível 3 HATEOAS Hypermedia GET /tasks/1 Inclui a navegação _links

(2) Uma explicação detalhada sobre o HATEOAS

O HATEOAS (Hypermedia as the Engine of Application State) exige que as respostas incluam links para operações relevantes, de modo que os clientes não precisem codificar URLs de forma estática.

JAVASCRIPT
app.get('/tasks/:id', (req, res) => {
  const task = tasks.find(t => t.id === parseInt(req.params.id));
  if (!task) return res.status(404).json({ error: 'Not found' });

  res.json({
    ...task,
    _links: {
      self: { href: `/tasks/${task.id}`, method: 'GET' },
      update: { href: `/tasks/${task.id}`, method: 'PUT' },
      delete: { href: `/tasks/${task.id}`, method: 'DELETE' },
      assign: { href: `/tasks/${task.id}/assignee`, method: 'POST' },
      comments: { href: `/tasks/${task.id}/comments`, method: 'GET' }
    }
  });
});
▶ Experimente
TEXT 📖 Somente leitura
// Response
{
  "id": "1",
  "タイトル": "Learn REST",
  "status": "pending",
  "createdAt": "2025-07-03T10:30:00Z",
  "_links": {
    "self": { "href": "/tasks/1", "method": "GET" },
    "update": { "href": "/tasks/1", "method": "PUT" },
    "remove": { "href": "/tasks/1", "method": "DELETE" },
    "assign": { "href": "/tasks/1/assignee", "method": "POST" },
    "comments": { "href": "/tasks/1/comments", "method": "GET" }
  }
}


9. Exemplo abrangente: projeto completo da API de gerenciamento de tarefas

A equipe de Alice desenvolveu uma API RESTful completa para o sistema de gerenciamento de tarefas, abrangendo tudo, desde as definições de recursos até o tratamento de erros.

▶ Exemplo: API de gerenciamento de tarefas completa

(1) Definição de recurso

Recurso Caminho Descrição
Coleção de tarefas /api/v1/tasks Todas as tarefas
Tarefa única /api/v1/tasks/:id Tarefa especificada
Comentários sobre a tarefa /api/v1/tasks/:id/comments Comentários sobre uma tarefa específica
Tag da tarefa /api/v1/tasks/:id/tags Tag para uma tarefa específica

(2) Mapeamento de métodos e solicitação/resposta

JAVASCRIPT 📖 Somente leitura
const express = require('express');
const app = express();
app.use(express.json());

let tasks = [
  { id: 1, title: 'Design database schema', status: 'done', priority: 'high', createdAt: '2025-07-01T08:00:00Z' },
  { id: 2, title: 'Implement REST API', status: 'in-progress', priority: 'high', createdAt: '2025-07-02T09:00:00Z' }
];
let nextId = 3;

// GET /api/v1/tasks — Get the task list
app.get('/api/v1/tasks', (req, res) => {
  const { status, priority, page = 1, limit = 20 } = req.query;
  let result = [...tasks];
  if (status) result = result.filter(t => t.status === status);
  if (priority) result = result.filter(t => t.priority === priority);

  const start = (page - 1) * limit;
  const data = result.slice(start, start + Number(limit));

  res.json({
    data,
    pagination: {
      page: Number(page),
      limit: Number(limit),
      total: result.length,
      totalPages: Math.ceil(result.length / Number(limit))
    }
  });
});

// GET /api/v1/tasks/:id — Get a Single Task
app.get('/api/v1/tasks/:id', (req, res) => {
  const task = tasks.find(t => t.id === parseInt(req.params.id));
  if (!task) {
    return res.status(404).json({
      error: 'Task not found',
      details: [{ field: 'id', message: `No task with id ${req.params.id}` }],
      timestamp: new Date().toISOString()
    });
  }
  res.json({
    data: task,
    _links: {
      self: { href: `/api/v1/tasks/${task.id}` },
      update: { href: `/api/v1/tasks/${task.id}`, method: 'PUT' },
      delete: { href: `/api/v1/tasks/${task.id}`, method: 'DELETE' },
      comments: { href: `/api/v1/tasks/${task.id}/comments` }
    }
  });
});

// POST /api/v1/tasks — Create a Task
app.post('/api/v1/tasks', (req, res) => {
  const { title, priority } = req.body;
  if (!title) {
    return res.status(400).json({
      error: 'Validation failed',
      details: [{ field: 'title', message: 'Title is required' }],
      timestamp: new Date().toISOString()
    });
  }
  const task = {
    id: nextId++,
    title,
    status: 'pending',
    priority: priority || 'medium',
    createdAt: new Date().toISOString()
  };
  tasks.push(task);
  res.status(201).location(`/api/v1/tasks/${task.id}`).json({ data: task });
});

// PUT /api/v1/tasks/:id — Full Update
app.put('/api/v1/tasks/:id', (req, res) => {
  const idx = tasks.findIndex(t => t.id === parseInt(req.params.id));
  if (idx === -1) {
    return res.status(404).json({
      error: 'Task not found',
      details: [{ field: 'id', message: `No task with id ${req.params.id}` }],
      timestamp: new Date().toISOString()
    });
  }
  const { title, status, priority } = req.body;
  if (!title || !status) {
    return res.status(400).json({
      error: 'Validation failed',
      details: [
        ...(!title ? [{ field: 'title', message: 'Title is required' }] : []),
        ...(!status ? [{ field: 'status', message: 'Status is required' }] : [])
      ],
      timestamp: new Date().toISOString()
    });
  }
  tasks[idx] = { id: tasks[idx].id, title, status, priority: priority || 'medium', createdAt: tasks[idx].createdAt };
  res.json({ data: tasks[idx] });
});

// PATCH /api/v1/tasks/:id — Partial Update
app.patch('/api/v1/tasks/:id', (req, res) => {
  const task = tasks.find(t => t.id === parseInt(req.params.id));
  if (!task) {
    return res.status(404).json({
      error: 'Task not found',
      details: [{ field: 'id', message: `No task with id ${req.params.id}` }],
      timestamp: new Date().toISOString()
    });
  }
  Object.assign(task, req.body);
  res.json({ data: task });
});

// DELETE /api/v1/tasks/:id — Delete Task
app.delete('/api/v1/tasks/:id', (req, res) => {
  const idx = tasks.findIndex(t => t.id === parseInt(req.params.id));
  if (idx === -1) {
    return res.status(404).json({
      error: 'Task not found',
      details: [{ field: 'id', message: `No task with id ${req.params.id}` }],
      timestamp: new Date().toISOString()
    });
  }
  tasks.splice(idx, 1);
  res.status(204).end();
});

app.listen(3000, () => console.log('Task API running on port 3000'));
111 linhas de lógica (limite de 40, somente leitura)

(3) Referência rápida para solicitações e respostas

BASH
# Create a Task
curl -X POST http://localhost:3000/api/v1/tasks \
  -H "Content-Type: application/json" \
  -d '{"title":"Write documentation","priority":"high"}'

# Get the task list(Filter + Pagination)
curl http://localhost:3000/api/v1/tasks?status=pending&page=1&limit=10

# Partial Update
curl -X PATCH http://localhost:3000/api/v1/tasks/1 \
  -H "Content-Type: application/json" \
  -d '{"status":"done"}'

# Delete Task
curl -X DELETE http://localhost:3000/api/v1/tasks/2
TEXT 📖 Somente leitura
// POST Created successfully → 201
Status: 201 Created
Location: /api/v1/tasks/3
{ "data": { "id": 3, "title": "Write documentation", "status": "pending", "priority": "high", "createdAt": "2025-07-03T10:30:00Z" } }

// PATCH Update successful → 200
{ "data": { "id": 1, "title": "Design database schema", "status": "done", "priority": "high", "createdAt": "2025-07-01T08:00:00Z" } }

// DELETE Success → 204
Status: 204 No Content
(empty body)

// 404 Error
{ "error": "Task not found", "details": [{ "field": "id", "message": "No task with id 999" }], "timestamp": "2025-07-03T10:30:00Z" }

// 400 Validation Error
{ "error": "Validation failed", "details": [{ "field": "title", "message": "Title is required" }], "timestamp": "2025-07-03T10:30:00Z" }

❓ Perguntas Frequentes

P: Qual é a diferença entre REST e GraphQL? R: O REST é baseado em recursos; cada URL corresponde a um recurso, que é manipulado por meio de métodos HTTP. O GraphQL é baseado em uma linguagem de consulta; os clientes recuperam campos sob demanda a partir de um único endpoint. O REST é adequado para cenários CRUD com recursos bem definidos, enquanto o GraphQL é adequado para consultas relacionais complexas.

P: Qual é a diferença entre PUT e PATCH? R: O PUT realiza uma substituição completa; é necessário fornecer todos os campos do recurso, e quaisquer campos ausentes serão definidos com seus valores padrão. O PATCH realiza uma atualização parcial; ele modifica apenas os campos fornecidos, enquanto os campos não fornecidos permanecem inalterados. O PUT é idempotente, enquanto não há garantia de que o PATCH seja idempotente.

P: Qual é a melhor maneira de versionar uma API? R: O versionamento por caminho de URL (/api/v1/) é o mais intuitivo; pode ser testado diretamente em um navegador e é a opção escolhida pela maioria das APIs públicas. O versionamento por cabeçalho de solicitação é mais RESTful, mas mais complicado de depurar. Os parâmetros de consulta são os mais simples, mas são facilmente ignorados. O versionamento por caminho de URL é recomendado para iniciantes.

P: Uma API REST precisa retornar JSON? R: Não necessariamente. O REST não restringe o formato; você pode usar XML, HTML, JSON e outros. No entanto, o JSON é atualmente o formato mais utilizado, pois é leve, fácil de analisar e compatível nativamente com JavaScript. Você pode negociar o formato usando o cabeçalho Content-Type.

P: O que é idempotência? R: Idempotência significa que executar a mesma solicitação uma vez produz o mesmo resultado que executá-la várias vezes. GET é idempotente (várias leituras produzem o mesmo resultado), PUT é idempotente (várias substituições produzem o mesmo resultado), DELETE é idempotente (excluir um recurso que já foi excluído ainda retorna um sucesso) e POST não é idempotente (ele cria um novo recurso a cada vez).

P: O que devo fazer se a hierarquia de recursos for muito profunda? R: Se a hierarquia exceder dois níveis de aninhamento, considere promover os recursos filhos a recursos de nível superior e vinculá-los por meio de parâmetros de consulta. Por exemplo, se /users/42/tasks/1/comments/5 for muito profundo, você pode alterá-lo para /comments/5 ou /tasks/1/comments/5.

P: Como uma API REST lida com operações em massa? R: Não existe uma abordagem padrão no REST. As práticas comuns incluem: usar uma solicitação POST /tasks/batch com um array para criar registros; usar uma solicitação PATCH /tasks com um array para atualizar registros em massa; e usar uma solicitação DELETE /tasks?ids=1,2,3 para excluir registros em massa. Os endpoints personalizados devem ser claramente documentados.


📖 Resumo


📝 Exercícios

  1. Conclua todos os exemplos de código desta lição e certifique-se de que cada um deles seja executado corretamente.
  2. Modifique o exemplo completo e adicione suas próprias extensões
  3. Analise a documentação oficial, identifique 1 ou 2 APIs que não foram abordadas nesta aula e escreva um código de teste para elas.
  4. Reflexão: Como você aplicaria o que aprendeu nesta aula a um projeto do mundo real?
  5. Tente combinar o que você aprendeu nesta aula com o conteúdo das aulas anteriores para criar um pequeno projeto.
Web-Tutorial.com

Equipe Técnica Web-Tutorial

Uma plataforma de tutoriais mantida por diversos desenvolvedores. Cada tutorial é escrito e revisado por profissionais da área correspondente. Trabalhamos para manter nosso conteúdo preciso e confiável — se encontrar algum problema, avise-nos.

100%