Preparando para integrar com Frontend

Área: Backend | Nível recomendado: Iniciante

Preparar aplicações backend para uma integração eficiente e segura com o frontend, implementando práticas essenciais de configuração de CORS, tratamento de erros e validação de dados, além de conhecer boas práticas no design de API focado no frontend.

Vídeo

Link direto: https://youtu.be/_FNqVtgfYQ0

Tópicos

  1. Introdução ao CORS:

    • Explicação do que é CORS e por que é necessário em aplicações modernas web.

    • Demonstração prática de como habilitar CORS em uma aplicação Express.js.

  2. Tratamento de Erros:

    • Boas práticas para o tratamento de erros para garantir que o frontend possa reagir adequadamente.

    • Implementação de tratamento de erros assíncronos usando express-async-errors.

    • Tratamento de rotas não encontradas (404) para retornar respostas JSON.

    • Tratamento de erros para ObjectId inválido no MongoDB.

  3. Validação de Dados:

    • Importância da validação de dados recebidos pelo backend.

    • Introdução às bibliotecas de validação de dados, como Joi.

    • Implementação de validações de payload usando Joi.

  4. Design de API focado no Frontend:

    • Princípios de design de API que facilitam o consumo pelo frontend.

    • Exemplos de como unificar endpoints e simplificar payloads para reduzir a carga no frontend.

    • Melhores práticas de design de API, incluindo consistência, documentação, paginação e versionamento.

Material de Apoio

Repositório no GitHub

PDF para Download

Miro

Exercícios de Fixação

Use esses exercícios para reforçar o que acabou de aprender. Se errar, leia a explicação para entender melhor o conceito.

Qual é a principal função do CORS em uma aplicação web?

A) Permitir que recursos restritos em uma página web sejam solicitados de um domínio diferente.

B) Proteger a aplicação contra ataques de injeção de SQL.

C) Garantir a segurança das senhas armazenadas no banco de dados.

D) Melhorar a performance da aplicação web.

Resposta correta

Qual é a principal função do CORS em uma aplicação web?

Resposta Correta: A

Feedback: CORS permite que recursos restritos em uma página web sejam solicitados de um domínio diferente, superando limitações de segurança dos navegadores.


Complete o código para configurar o middleware de CORS em uma aplicação Express.js.
const express = require('express');
const cors = require('cors');
const app = express();

app.use(________);

app.listen(3000, function () {
  console.log("Aplicação rodando em http://localhost:3000");
});
Resposta correta

Complete o código para configurar o middleware de CORS em uma aplicação Express.js.

Resposta Correta:

app.use(cors());

Feedback: O middleware cors() habilita CORS na aplicação, permitindo que ela responda a requisições de diferentes domínios.


Verdadeiro ou Falso: O middleware express-async-errors simplifica o tratamento de erros assíncronos em uma aplicação Express.js.

A) Verdadeiro

B) Falso

Resposta correta

Verdadeiro ou Falso: O middleware express-async-errors simplifica o tratamento de erros assíncronos em uma aplicação Express.js.

Resposta Correta: A

Feedback: Verdadeiro. O express-async-errors simplifica o tratamento de erros assíncronos, passando automaticamente os erros para o middleware de tratamento de erros padrão do Express.


Complete o código para validar um ObjectId do MongoDB e retornar um erro apropriado se o ObjectId for inválido.
const { ObjectId } = require('mongodb');

function validateObjectId(req, res, next) {
  const id = req.params.id;

  if (!ObjectId.________(id)) {
    return res.status(400).send({ error: 'ObjectId inválido' });
  }

  next();
}

module.exports = {
  validateObjectId
}
Resposta correta

Complete o código para validar um ObjectId do MongoDB e retornar um erro apropriado se o ObjectId for inválido.

Resposta Correta:

if (!ObjectId.isValid(id)) {
  return res.status(400).send({ error: 'ObjectId inválido' });
}

Feedback: A função ObjectId.isValid(id) verifica se o ID fornecido é válido, retornando um erro 400 se não for.


Qual é a principal vantagem de utilizar a biblioteca Joi para validação de dados?

A) Simplificar a validação de esquemas complexos.

B) Melhorar a performance do banco de dados.

C) Garantir a segurança das senhas armazenadas.

D) Facilitar a configuração de variáveis de ambiente.

Resposta correta

Qual é a principal vantagem de utilizar a biblioteca Joi para validação de dados?

Resposta Correta: A

Feedback: A biblioteca Joi simplifica a validação de esquemas complexos, melhorando a legibilidade do código e fornecendo mensagens de erro detalhadas.

Exercícios de Validação

Esses exercícios testarão sua compreensão prática. Revise o feedback para melhorar suas habilidades.

Desafio de Código

Implemente a validação de dados e o tratamento de erros usando Joi e middlewares em uma aplicação Express.

Arquivo Inicial

index.js
const express = require('express');
const app = express();
app.use(express.json());

const tarefas = [];

app.post('/tarefas', function (req, res) {
  const novaTarefa = req.body;

  if (!novaTarefa.titulo || !novaTarefa.descricao || !novaTarefa.status) {
    return res.status(400).send('Corpo da requisição deve conter as propriedades titulo, descricao e status.');
  }

  tarefas.push(novaTarefa);
  res.status(201).send(novaTarefa);
});

app.listen(3000, function () {
  console.log("Servidor rodando em http://localhost:3000");
});

Tarefas

  • Validação de Dados com Joi:

    • Implemente a validação de dados recebidos no endpoint /tarefas usando Joi.

  • Tratamento de Erros:

    • Adicione middlewares para tratamento de erros na aplicação.

  • Configuração de CORS:

    • Habilite CORS na aplicação.

Código Esperado

Validação de Dados e Tratamento de Erros

index.js
const express = require('express');
const cors = require('cors');
const Joi = require('joi');
const app = express();
app.use(express.json());
app.use(cors());

const tarefas = [];

const tarefaSchema = Joi.object({
  titulo: Joi.string().min(3).required(),
  descricao: Joi.string().min(5).required(),
  status: Joi.string().valid('pendente', 'concluída').required()
});

app.post('/tarefas', function (req, res, next) {
  const { error, value } = tarefaSchema.validate(req.body);

  if (error) {
    return res.status(400).send(error.details[0].message);
  }

  tarefas.push(value);
  res.status(201).send(value);
});

app.use(function (err, req, res, next) {
  console.error(err.stack);
  res.status(500).send('Algo deu errado!');
});

app.listen(3000, function () {
  console.log("Servidor rodando em http://localhost:3000");
});

Feedback: Certifique-se de validar os dados recebidos com Joi e trate adequadamente os erros usando middlewares. Habilite CORS para permitir requisições de diferentes origens.

Revisão de Código

Analise o código a seguir, encontre e corrija o erro relacionado à configuração de CORS e tratamento de erros na integração com frontend.

index.js
const express = require('express');
const app = express();
app.use(express.json());

const tarefas = [];

app.post('/tarefas', function (req, res) {
  const novaTarefa = req.body;

  if (!novaTarefa.titulo || !novaTarefa.descricao || !novaTarefa.status) {
    return res.status(400).send('Corpo da requisição deve conter as propriedades titulo, descricao e status.');
  }

  tarefas.push(novaTarefa);
  res.status(201).send(novaTarefa);
});

app.use(function (err, req, res, next) {
  console.error(err.stack);
  res.status(500).send('Algo deu errado!');
});

app.listen(3000, function () {
  console.log("Servidor rodando em http://localhost:3000");
});
Resposta Correta

Erros:

  1. Falta a configuração do CORS para permitir requisições de diferentes origens.

  2. O tratamento de erros não está configurado para lidar com erros assíncronos corretamente.

Código Corrigido:

index.js
const express = require('express');
const cors = require('cors');
require('express-async-errors');
const app = express();
app.use(express.json());
app.use(cors());

const tarefas = [];

app.post('/tarefas', function (req, res) {
  const novaTarefa = req.body;

  if (!novaTarefa.titulo || !novaTarefa.descricao || !novaTarefa.status) {
    return res.status(400).send('Corpo da requisição deve conter as propriedades titulo, descricao e status.');
  }

  tarefas.push(novaTarefa);
  res.status(201).send(novaTarefa);
});

app.use(function (err, req, res, next) {
  console.error(err.stack);
  res.status(500).send('Algo deu errado!');
});

app.listen(3000, function () {
  console.log("Servidor rodando em http://localhost:3000");
});

Feedback: Certifique-se de habilitar CORS para permitir requisições de diferentes origens e configure o tratamento de erros para lidar com erros assíncronos corretamente.

Projeto Prático

Implemente um endpoint para criar tarefas em uma aplicação ExpressJS. As tarefas devem ter as propriedades "título", "descrição" e "status". Utilize CORS, valide os dados usando Joi e implemente o tratamento de erros.

Arquivo Inicial

const express = require('express');
const cors = require('cors');
const Joi = require('joi');
const app = express();

app.use(express.json());
app.use(cors());

const tarefas = [];

const tarefaSchema = Joi.object({
  titulo: Joi.string().min(3).required(),
  descricao: Joi.string().min(5).required(),
  status: Joi.string().valid('pendente', 'concluída').required()
});

app.post('/tarefas', function (req, res, next) {
  const { error, value } = tarefaSchema.validate(req.body);

  if (error) {
    return res.status(400).send(error.details[0].message);
  }

  tarefas.push(value);
  res.status(201).send(value);
});

app.use(function (err, req, res, next) {
  console.error(err.stack);
  res.status(500).send('Algo deu errado!');
});

app.listen(3000, function () {
  console.log("Servidor rodando em http://localhost:3000");
});

Tarefas

  • Validação de Dados com Joi:

    • Implemente a validação de dados recebidos no endpoint /tarefas usando Joi.

  • Tratamento de Erros:

    • Adicione middlewares para tratamento de erros na aplicação.

  • Configuração de CORS:

    • Habilite CORS na aplicação.

Código Esperado
index.js
const express = require('express');
const cors = require('cors');
const Joi = require('joi');
const app = express();

app.use(express.json());
app.use(cors());

const tarefas = [];

const tarefaSchema = Joi.object({
  titulo: Joi.string().min(3).required(),
  descricao: Joi.string().min(5).required(),
  status: Joi.string().valid('pendente', 'concluída').required()
});

app.post('/tarefas', function (req, res, next) {
  const { error, value } = tarefaSchema.validate(req.body);

  if (error) {
    return res.status(400).send(error.details[0].message);
  }

  tarefas.push(value);
  res.status(201).send(value);
});

app.use(function (err, req, res, next) {
  console.error(err.stack);
  res.status(500).send('Algo deu errado!');
});

app.listen(3000, function () {
  console.log("Servidor rodando em http://localhost:3000");
});

Feedback Detalhado

  • Verificação do Endpoint: Certifique-se de testar a rota /tarefas acessando http://localhost:3000 e verificando as respostas.

  • Validação de Dados: Garanta que os dados recebidos pelo backend são validados corretamente usando Joi, e que erros de validação são tratados adequadamente.

  • Configuração de CORS: Verifique se o CORS está configurado corretamente para permitir requisições de diferentes origens.

  • Tratamento de Erros: Confirme se o tratamento de erros assíncronos está funcionando como esperado e se os erros são corretamente registrados e retornados.

Last updated