Express - Middlewares
Tags: node, beginners, webdev, braziliandevs
Published: 2022-03-17 22:24:38

## Tabela de Conteúdos

- [Middleware](#middlewares)
- [Middleware Globais](#middlewares-globais)
- [Valores entre Middleware](#valores-entre-middlewares)
- [Router](#router)
- [Tratando Erros](#tratando-erros)
- [Express-rescue](#express-rescue)
- [Links Úteis](#links-úteis)

---

## Middlewares

### O que são?

__São quaisquer funções passadas de forma direta ou indireta para uma rota__, recebendo até três parâmetros, sendo os dois primeiros o objeto de requisição e de resposta, respectivamente e o terceiro é uma callback que aciona o próximo Middleware.

_** Middlewares que recebem quatro parâmetros são Middlewares de Erro e iremos aborda-los mais a frente._

### O que faz?

Por serem funções, os Middlewares podem realizar diversas ações diferentes, tudo depende daquilo que queremos/precisamos fazer. Porém todo o Middleware __sempre pode realizar essas três ações: manipular a requisição; enviar uma resposta; e/ou chamar o próximo middleware__.

### Sintaxe

Como vimos em sua definição, Middlewares são funções, que podem ser passadas direta ou indiretamente para a rota, a única diferença dos Middlewares para funções puras são os parâmetros recebidos.

Middlewares recebem por padrão três parâmetros, a requisição `req`, a resposta `res` e a referência ao próximo Middleware `next`.

``` javascript
function myMiddleware(req, res, next) {}
api.get(/*rota*/, myMiddleware);

const myMiddleware = (req, res, next) => {};
api.get(/*rota*/, myMiddleware);

app.get(/*rota*/, (req, res, next) => {});
```

Lembrando que não precisamos passar sempre uma arrow function como Middleware, podemos definir uma função previamente e passá-la como callback, __sempre respeitando os parâmetros de um Middleware__.

<br />

<small>[Voltar ao topo](#tabela-de-conteúdos)</small>

___

## Middlewares Globais

### O que são?

São funções que serão executadas antes, ou depois, de qualquer outro Middleware, sua ordem de execução depende diretamente do seu posicionamento no código.

### O que fazem?

Middlewares globais normalmente são usados para autenticação, tratamento prévio dos dados e/ou tratamento de erros.

### Sintaxe

Assim como qualquer Middleware, um global também é constituído de uma função de até três parâmetros, porém a __diferença é que iremos chamar ele no `app.use()`__, assim toda e qualquer rota definida abaixo do método `.use()` será executada somente após o Middleware global.

``` javascript
app.use((req, res, next) => {});
```

<br />

<small>[Voltar ao topo](#tabela-de-conteúdos)</small>

___

## Valores entre Middlewares

### Como fazer?

Para conseguirmos passar valores entre Middlewares, utilizamos o objeto de requisição `req` como um intermediário, dessa forma a chave que alterarmos/adicionarmos nesse objeto será refletida no próximo Middleware.

``` javascript
const firstMiddleware = (req, res, next) => {
  req.user = { name: 'usuario', password: 'abc123' };
  next();
};
```

Não passamos os valores através de parâmetros para a callback `next()`, pois caso passássemos, o próximo Middleware a ser chamado seria um Middleware de Erro e não um Middleware _"comum"_.

Lembrando que a chave não precisa existir previamente no objeto.

<br />

<small>[Voltar ao topo](#tabela-de-conteúdos)</small>

___

## Router

### O que é?

É um método do Express que permite agrupar diversos endpoints em um único arquivo.

### O que faz?

Permite a fragmentação das rotas em diversos arquivos, algo similar ao que ocorre no React com os componentes.

### Sintaxe

#### Criação

Como o Router é um método que permite a fragmentação do código em diferentes arquivos, o primeiro passo é criar um novo arquivo para guardar os endpoints de determinada rota.

Com o arquivo criado, precisamos importar o Express e a partir dele gerar nosso router, para isso executamos o método `.Router()` do Express e armazenamos seu retorno em uma constante, convencionalmente chamada de router.

Tendo o router criado, a sintaxe de criação de endpoint segue a mesma, com a diferença que não usamos mais o objeto app, mas sim o router que criamos. Ao final da criação dos endpoints é necessário exportar somente o router.

``` javascript
// routes/myRouter.js

const express = require('express');
const router = express.Router();

myRoute.get('/', (req, res) => {});
myRoute.post('/', (req, res) => {});

module.exports = myRoute;
```

#### Uso

Para usarmos os endpoints criados em um arquivo externo é muito simples, em nosso arquivo principal (normalmente index.js) importamos o router criado no outro arquivo, para isso chamamos a função `require()` passando o path como parâmetro e armazenando seu retorno em uma constante, essa que pode receber qualquer nome.

Com o router contendo os endpoints importados, tudo que precisamos fazer é utilizar o método `.use()` passando dois parâmetros, o primeiro será a rota daqueles endpoints e o segundo o router que acabamos de importar.

``` javascript
// src/index.js

const myRouter = require('./myRouter');

app.use('/someRoute', myRouter);
```

<br />

<small>[Voltar ao topo](#tabela-de-conteúdos)</small>

___

## Tratando Erros

### Por que fazer?

Precisamos tratar o erro dentro da API, porque caso não o fizermos e a nossa aplicação quebrar, o erro irá aparecer de forma _"crua"_ para o usuário, deixando nossa aplicação vulnerável.

### Como fazer?

O tratamento de erros dentro do Express se dá através de Middlewares de Erros, esses que são similares aos outros que vimos até então, com uma única diferença, esse recebe quatro parâmetros obrigatórios.

Além dos três parâmetros base, `req`, `res` e `next`, também recebe o erro como primeiro argumento. Sendo assim, __mesmo que não usemos os outros argumentos, é necessário passá-los__, isso porque o Express identifica um Middleware de Erro a partir do número de parâmetros.

### Sintaxe

Como visto anteriormente, o Middleware de erro precisa receber quatro parâmetros sendo eles o de erro `err`, o de requisição `req`, o de resposta `res` e o de chamada ao próximo `next`.

Além disso, esses Middlewares __precisam ser definidos por último__, a partir do método `.use()`. E __para executá-los usamos a callback `next()`, passando um parâmetro para ela__, dessa forma o Express sabe que o próximo Middleware a ser executado é para o tratamento de erros.

``` javascript
app.get(/*rota*/, (req, res, next) => {
  try {
    /*bloco de lógica*/
  } catch (err) {
    next(err)
  }
});

app.use((err, req, res, next) => {});
```

<br />

<small>[Voltar ao topo](#tabela-de-conteúdos)</small>

___

## Express-rescue

### O que é?

É um pacote externo do Node, disponível via NPM. Para instalar esse pacote basta utilizar o comando:

``` bash
npm i express-rescue
```

### O que faz?

Esse pacote facilita a escrita de Middlewares com tratamento de erro _"embutido"_, dessa forma o código fica mais enxuto e legível.

### Sintaxe

Após termos instalado o pacote, tudo que precisamos fazer é importá-lo e chamá-lo como Middleware do endpoint, passando uma callback como parâmetro, essa que irá receber os três parâmetros comuns aos Middlewares (req, res e next).

``` javascript
const rescue = require('express-rescue');

app.get('/', rescue((req, res, next) => {}));
```

<br />

<small>[Voltar ao topo](#tabela-de-conteúdos)</small>

---

## Links Úteis

- [Detalhes das Rotas do Express](https://dev.to/gabrielhsilvestre/o-basico-express-rotas-4i70)
- [Express docs](http://expressjs.com/en/4x/api.html)
- [Express docs - Rotas](https://expressjs.com/pt-br/guide/routing.html)
- [Express docs - Middleware](https://expressjs.com/pt-br/guide/writing-middleware.html)
- [DevHints - Express Cheat Sheet](https://devhints.io/express)
- [Express-rescue docs](https://github.com/rwillians/express-rescue)
- [Error Handler](https://medium.com/pagarme/minha-experi%C3%AAncia-com-error-handling-no-express-188534ae6ff2) por Matheus Vellone