> For the complete documentation index, see [llms.txt](https://salvatore-academy.gitbook.io/dev-fullstack-web/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://salvatore-academy.gitbook.io/dev-fullstack-web/academia/missoes-de-backend/preparando-para-integrar-com-frontend.md).

# Preparando para integrar com Frontend

Área: Backend | Nível recomendado: Iniciante

{% hint style="info" %}
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.
{% endhint %}

## Vídeo

{% embed url="<https://youtu.be/_FNqVtgfYQ0>" %}

**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

{% embed url="<https://github.com/SalvatoreAcademy/backend-missao-aprendizado-iniciante-preparando-para-integrar-com-frontend>" %}

### PDF para Download

{% file src="/files/Gh6lSyoIVKakVyI1owiO" %}

### Miro

{% embed url="<https://miro.com/app/board/uXjVNQ6PZjQ=/?moveToWidget=3458764587647670430&cot=14>" %}

## Exercícios de Fixação

{% hint style="info" %}
Use esses exercícios para reforçar o que acabou de aprender. Se errar, leia a explicação para entender melhor o conceito.
{% endhint %}

<details>

<summary>Qual é a principal função do CORS em uma aplicação web?</summary>

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.

</details>

<details>

<summary>Resposta correta</summary>

**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.

</details>

***

<details>

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

{% code lineNumbers="true" %}

```javascript
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");
});
```

{% endcode %}

</details>

<details>

<summary>Resposta correta</summary>

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

**Resposta Correta**:

```javascript
app.use(cors());
```

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

</details>

***

<details>

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

A) Verdadeiro

B) Falso

</details>

<details>

<summary>Resposta correta</summary>

**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.

</details>

***

<details>

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

{% code lineNumbers="true" %}

```javascript
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
}
```

{% endcode %}

</details>

<details>

<summary>Resposta correta</summary>

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

**Resposta Correta**:

```javascript
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.

</details>

***

<details>

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

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.

</details>

<details>

<summary>Resposta correta</summary>

**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.

</details>

## Exercícios de Validação

{% hint style="info" %}
Esses exercícios testarão sua compreensão prática. Revise o feedback para melhorar suas habilidades.
{% endhint %}

### 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

{% code title="index.js" lineNumbers="true" %}

```javascript
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");
});
```

{% endcode %}

#### 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**

{% code title="index.js" lineNumbers="true" %}

```javascript
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");
});
```

{% endcode %}

**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

{% hint style="danger" %}
**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.**
{% endhint %}

{% code title="index.js" lineNumbers="true" %}

```javascript
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");
});
```

{% endcode %}

<details>

<summary>Resposta Correta</summary>

**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:**

{% code title="index.js" lineNumbers="true" %}

```javascript
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");
});
```

{% endcode %}

**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.

</details>

### 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

```javascript
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.

<details>

<summary>Código Esperado</summary>

{% code title="index.js" lineNumbers="true" %}

```javascript
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");
});
```

{% endcode %}

**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.

</details>
