Middlewares no Express: Tudo que você precisa saber!

English Article

Podemos falar que middlewares são, Funcões que rodam entre o objeto request e o response de uma aplicação. Com eles, podemos executar qualquer código durante esse processo, encerrar o response ou até mesmo modificar os objetos req e res.

Escrevendo um Middleware simples

Vamos escrever uma função chamada simpleMiddleware como nosso middleware, e depois disso, usaremos app.use(simpleMiddleware) para nosso app.get('/') ter acesso à ela.


_15
const express = require('express')
_15
const app = express()
_15
_15
const simpleMiddleware = (req, res, next) => {
_15
console.log('Middleware funcionando!')
_15
next()
_15
}
_15
_15
app.use(simpleMiddleware)
_15
_15
app.get('/', (req, res) => {
_15
res.send('<h1>Hello World!</h1>')
_15
})
_15
_15
app.listen(3000)

Quando acessamos http://localhost:3000/ vamos receber a mensagem "Middleware funcionando!". Perceba que não vamos receber o console.log() no browser, o Node.js roda no V8 Engine do JavaScript e não tem acesso ao nosso browser!

Usando um Middleware: Global

No exemplo acima, usamos app.use(), se por acaso temos mais rotas neste arquivo, o Middleware será usado em todos, por isso chamados de uso global. É importante resaltar que eles são chamados na ordem que são definidos. Veja o exemplo:


_13
...
_13
_13
app.get("/", (req, res) => {
_13
res.send("<h1>Hello World!</h1>");
_13
});
_13
_13
app.use(simpleMiddleware)
_13
_13
app.get("/about", (req, res) => {
_13
res.send("<h1>About Page!</h1>");
_13
});
_13
_13
...

O nosso Middleware apenas será chamado caso hajá alguém acessando a página http://localhost:3000/About, a página principal será ignorada. O uso global pode ser útil quando organizamos as rotas por arquivos e tipos!

Usando um Middleware: Rota

Caso queira usar por rota, você pode adicionar o nome do Middleware entre os objetos req e res. Veja o exemplo


_7
...
_7
_7
app.get("/", simpleMiddleware, (req, res) => {
_7
res.send("<h1>Hello World!</h1>");
_7
});
_7
_7
...

ou assim


_7
...
_7
_7
app.get("/", (req, res, next) => {
_7
res.send("<h1>Hello World!</h1>");
_7
});
_7
_7
...

Preferência por Middlewares: Global vs Rota

Saiba que quando usamos app.use(middleware), ele tem uma preferência maior que o por rota, ou seja, ele irá ser chamado primeiro.


_8
app.use(myGlobalMiddleware)
_8
_8
app.get('/about', myRouteMiddleware, (req, res) => {
_8
res.send('About page')
_8
})
_8
_8
// myGlobalMiddleware é chamado
_8
// myRouteMiddleware é chamado

Comunicação entre Middlewares

Podemos passar informações entre Middleware ao modificar os seus objetos req e res. Veja o exemplo


_12
const autorizarMaioresDeIdade = (req, res, next) => {
_12
if (req.query.idade >= '18') {
_12
req.autorizado = true
_12
next()
_12
} else {
_12
res.send('ERRO: Você é menor de idade')
_12
}
_12
}
_12
_12
app.get('/', autorizarMaioresDeIdade, (req, res) => {
_12
res.send(`<h1>Página principal <br/> Autorizado = ${req.autorizado} </h1>`)
_12
})

Ao acessar com http://localhost:3000/?idade=18, o Middleware nos autoriza por termos os requisitos necessários, e logo depois, renderiza a página com a mensagem: Autorizado true.

Evite erros usando Middlewares

Nos exemplos anteriores, usamos um if e else para determinar se o usuário é maior de idade, mas e se quisermos "encurtar" o código com a intenção de deixá-lo mais limpo? A primeira coisa que alguém pensa é em deixar assim:


_7
const autorizarMaioresDeIdade = (req, res, next) => {
_7
if (req.query.idade >= '18') {
_7
req.autorizado = true
_7
next()
_7
}
_7
res.send('ERRO: Você é menor de idade')
_7
}

O express roda códigos mesmo depois do next(), portanto, o usuário seria autorizado e logo depois receberia um erro! Por mais chato que seja, essa maneira que o express usa em Middlewares abre mais uma oportunidade para que rodamos algum código após o objeto response.