Escrever middleware para utilização em aplicações Express

Overview

Funções de middleware são funções que têm acesso ao objecto pedido (req), o objecto de resposta (res), e a função next no ciclo de resposta de solicitação da aplicação. A função next é uma função no router Express que, quando invocada, executa o middleware que sucede ao middleware actual.

Funções de middleware podem executar as seguintes tarefas:

  • Executar qualquer código.
  • Fazer alterações ao pedido e aos objectos de resposta.
  • Fim do ciclo de resposta ao pedido.
  • li>Chamar o próximo middleware na pilha.

Se a função middleware actual não terminar o ciclo de resposta ao pedido, deve chamar next() para passar o controlo para a próxima função middleware. Caso contrário, o pedido será deixado pendurado.

A figura seguinte mostra os elementos de uma função de middleware chamada:

métodoHTTP ao qual se aplica a função de middleware.
Caminho (rota) ao qual se aplica a função middleware.
A função middleware.
Argumento de retorno para a função middleware, chamado “next” por convenção.
Disc>Disc>Disc>Disc>HTTP argumento de resposta à função de middleware, chamado “res” por convenção.
Disc>Disc>HTTP argumento de pedido à função de middleware, chamado “req” por convenção.

Começar com o Express 5, funções de middleware que retornam uma promessa chamarão next(value) quando rejeitarem ou atirarem um erro. next será chamado com o valor rejeitado ou o Erro lançado.

Exemplo

Aqui está um exemplo de uma aplicação simples “Hello World” Express.O resto deste artigo irá definir e adicionar três funções de middleware à aplicação:uma chamada myLogger que imprime uma simples mensagem de registo, outra chamada requestTime que exibe o carimbo da hora do pedido HTTP, e outra chamada validateCookies que valida os cookies recebidos.

var express = require('express')var app = express()app.get('/', function (req, res) { res.send('Hello World!')})app.listen(3000)

Função middleware myLogger

Aqui está um exemplo simples de uma função middleware chamada “myLogger”. Esta função apenas imprime “LOGGED” quando um pedido para a aplicação passa por ela. A função de middleware é atribuída a uma variável chamada myLogger.

Nota a chamada acima para next(). A chamada a esta função invoca a próxima função middleware no app.The next() function is not a part of the Node.js or Express API, mas é o terceiro argumento que é passado para a função middleware. A função next() poderia ser nomeada qualquer coisa, mas por convenção é sempre nomeada “next”.Para evitar confusão, usar sempre esta convenção.

Para carregar a função middleware, chamar app.use(), especificando a função middleware.Por exemplo, o seguinte código carrega o myLogger função middleware antes da rota para o caminho raiz (/).

var express = require('express')var app = express()var myLogger = function (req, res, next) { console.log('LOGGED') next()}app.use(myLogger)app.get('/', function (req, res) { res.send('Hello World!')})app.listen(3000)

Sempre que a aplicação recebe um pedido, imprime a mensagem “LOGGED” para o terminal.

A ordem de carregamento do middleware é importante: as funções de middleware que são carregadas primeiro também são executadas primeiro.

Se myLogger for carregado após a rota para o caminho de raiz, o pedido nunca o atinge e a aplicação não imprime “LOGGED”, porque o manipulador da rota do caminho de raiz termina o ciclo de resposta do pedido.

A função middleware myLogger simplesmente imprime uma mensagem, depois passa o pedido para a próxima função middleware na pilha chamando a função next().

Middleware function requestTime

Next, vamos criar uma função de middleware chamada “requestTime” e adicionar uma propriedade chamada requestTime ao objecto de pedido.

var requestTime = function (req, res, next) { req.requestTime = Date.now() next()}

O aplicativo agora usa a função requestTime middleware. Além disso, a função callback da rota do caminho da raiz utiliza a propriedade que a função middleware adiciona a req (o objecto de pedido).

var express = require('express')var app = express()var requestTime = function (req, res, next) { req.requestTime = Date.now() next()}app.use(requestTime)app.get('/', function (req, res) { var responseText = 'Hello World!<br>' responseText += '<small>Requested at: ' + req.requestTime + '</small>' res.send(responseText)})app.listen(3000)

Quando faz um pedido à raiz da aplicação, a aplicação exibe agora o carimbo temporal do seu pedido no browser.

Função de middleware validarCookies

Finalmente, vamos criar uma função de middleware que valida os cookies recebidos e envia uma resposta de 400 se os cookies forem inválidos.

Aqui está uma função de exemplo que valida os cookies com um serviço externo assimétrico.

async function cookieValidator (cookies) { try { await externallyValidateCookie(cookies.testCookie) } catch { throw new Error('Invalid cookies') }}

Aqui usamos a função cookie-parser middleware para analisar os cookies recebidos no objecto req e passá-los à nossa função cookieValidator. O validateCookies middleware retorna uma promessa de que ao ser rejeitado irá automaticamente accionar o nosso manipulador de erros.

var express = require('express')var cookieParser = require('cookie-parser')var cookieValidator = require('./cookieValidator')var app = express()async function validateCookies (req, res, next) { await cookieValidator(req.cookies) next()}app.use(cookieParser())app.use(validateCookies)// error handlerapp.use(function (err, req, res, next) { res.status(400).send(err.message)})app.listen(3000)

Nota como next() é chamado após await cookieValidator(req.cookies). Isto assegura que se cookieValidator resolver, o próximo middleware na pilha será chamado. Se passar qualquer coisa à função next() (excepto a string 'route' ou 'router'), a Express considera o pedido actual como sendo um erro e salta qualquer resto de funções de encaminhamento e middleware não relacionadas com o manuseamento de erros.

Porque tem acesso ao objecto de pedido, ao objecto de resposta, à próxima função de middleware na pilha, e a todo o Node.js API, as possibilidades com funções de middleware são infinitas.

Para mais informações sobre o middleware Express, ver: Usando o middleware Express.

Middleware configurável

Se precisar que o seu middleware seja configurável, exporte uma função que aceite um objecto de opções ou outros parâmetros, que, depois, devolve a implementação do middleware com base nos parâmetros de entrada.

Arquivo: my-middleware.js

module.exports = function (options) { return function (req, res, next) { // Implement the middleware function based on the options object next() }}

O middleware pode agora ser usado como se mostra abaixo.

var mw = require('./my-middleware.js')app.use(mw({ option1: '1', option2: '2' }))

Refer a cookie-session e compressão para exemplos de middleware configurável.

Deixe uma resposta

O seu endereço de email não será publicado. Campos obrigatórios marcados com *