Escrever middleware para uso nos aplicativos Express
Middleware_ são funções que têm acesso ao objeto de requisição (req), a objeto de resposta (res) e a função next no ciclo de resposta de solicitação do aplicativo. A função próxima é uma função no roteador Expresso que, quando invocado, executa o intermediário sucedendo ao intermediário atual.
As funções do Middleware podem executar as seguintes tarefas:
- Execute qualquer código.
- Fazer alterações na solicitação e nos objetos de resposta.
- Encerrar o ciclo de solicitação-resposta.
- Chame o próximo middleware na pilha.
Se a função middleware atual não encerra o ciclo de resposta de solicitação, ela deve chamar next() para passar o controle para a próxima função middleware. Caso contrário, o pedido ficará pendurado.
A figura a seguir mostra os elementos de uma chamada de função middleware:

Começando com as funções de middleware Express, funções de intermediário que retornam uma Promessa chamarão próximo(valor) quando eles rejeitarem ou lançarem 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.
The remainder of this article will define and add three middleware functions to the application:
one called myLogger that prints a simple log message, one called requestTime that
displays the timestamp of the HTTP request, and one called validateCookies that validates incoming cookies.
const express = require('express');const app = express();
app.get('/', (req, res) => { res.send('Hello World!');});
app.listen(3000);import express from 'express';
const app = express();
app.get('/', (req, res) => { res.send('Hello World!');});
app.listen(3000);import express, { type Express, type Request, type Response } from 'express';
const app: Express = express();
app.get('/', (req: Request, res: Response) => { res.send('Hello World!');});
app.listen(3000);Função Middleware myLogger
Aqui está um exemplo simples de uma função de middleware chamada “myLogger”. Essa função apenas imprime
“LOGGGED” quando uma solicitação para o aplicativo passa por ela. A função middleware está atribuída a uma variável
chamada myLogger.
const myLogger = function (req, res, next) { console.log('LOGGED'); next();};import { type Request, type Response, type NextFunction } from 'express';
const myLogger = function (req: Request, res: Response, next: NextFunction) { console.log('LOGGED'); next();};Here myLogger is defined on its own rather than passed directly to app.use(), so TypeScript has
no context to infer its parameters and they are annotated explicitly. You can instead type the whole
function as RequestHandler, which types req, res, and next for you. When the middleware is
written inline in the app.use() call, Express infers those three parameters and no annotations are
needed.
Observe a chamada acima para next(). Chamar esta função chama a próxima função de middleware em
o aplicativo. A função next() não é parte do Node. s ou API Expressa, mas é o terceiro argumento
que é passado para a função middleware. A função next() pode ser nomeada qualquer coisa,
mas por convenção é sempre chamada de “next”. Para evitar confusões, utilize sempre esta convenção.
Para carregar a função middleware, chame app.use(), especificando a função middleware.
Por exemplo, o código a seguir carrega a função myLogger middleware antes da rota para o caminho raiz (/).
const express = require('express');const app = express();
const myLogger = function (req, res, next) { console.log('LOGGED'); next();};
app.use(myLogger);
app.get('/', (req, res) => { res.send('Hello World!');});
app.listen(3000);import express from 'express';
const app = express();
const myLogger = function (req, res, next) { console.log('LOGGED'); next();};
app.use(myLogger);
app.get('/', (req, res) => { res.send('Hello World!');});
app.listen(3000);import express, { type Express, type Request, type Response, type NextFunction } from 'express';
const app: Express = express();
const myLogger = function (req: Request, res: Response, next: NextFunction) { console.log('LOGGED'); next();};
app.use(myLogger);
app.get('/', (req: Request, res: Response) => { res.send('Hello World!');});
app.listen(3000);Toda vez que o aplicativo recebe uma solicitação, ele imprime a mensagem “LOGGED” no terminal.
A ordem do carregamento do middleware é importante: as funções de middleware que são carregadas primeiro também são executadas primeiro.
Se o myLogger é carregado após a rota para o caminho raiz, a solicitação nunca chega a ela e o aplicativo não imprime “LOGGED”, porque o gerenciador de rotas do caminho raiz termina o ciclo de resposta-requisição.
A função middleware myLogger simplesmente imprime uma mensagem, então passa a requisição para a próxima função de middleware na pilha chamando a função next().
Tempo de solicitação de função Middleware
Em seguida, vamos criar uma função middleware chamada “requestTime” e adicionar uma propriedade chamada requestTime
ao objeto solicitado.
Because the middleware adds a property to req, extend the request type in TypeScript with
declaration merging. Declare
the property (as optional, since a middleware may not run for every request) in a .d.ts file that
is part of your project:
declare global { namespace Express { interface Request { requestTime?: number; } }}
export {};TypeScript picks up the file automatically, so no tsconfig.json change is needed unless you have
set a custom include that does not cover its location. See
Extending the API in TypeScript for
adding other custom properties and methods.
const requestTime = function (req, res, next) { req.requestTime = Date.now(); next();};import { type Request, type Response, type NextFunction } from 'express';
const requestTime = function (req: Request, res: Response, next: NextFunction) { req.requestTime = Date.now(); next();};O aplicativo agora usa a função middleware requestTime. Além disso, a função de retorno de chamada da rota raiz usa a propriedade que a função middleware adiciona a req (o objeto de solicitação).
const express = require('express');const app = express();
const requestTime = function (req, res, next) { req.requestTime = Date.now(); next();};
app.use(requestTime);
app.get('/', (req, res) => { let responseText = 'Hello World!<br>'; responseText += `<small>Requested at: ${req.requestTime}</small>`; res.send(responseText);});
app.listen(3000);import express from 'express';
const app = express();
const requestTime = function (req, res, next) { req.requestTime = Date.now(); next();};
app.use(requestTime);
app.get('/', (req, res) => { let responseText = 'Hello World!<br>'; responseText += `<small>Requested at: ${req.requestTime}</small>`; res.send(responseText);});
app.listen(3000);import express, { type Express, type Request, type Response, type NextFunction } from 'express';
const app: Express = express();
const requestTime = function (req: Request, res: Response, next: NextFunction) { req.requestTime = Date.now(); next();};
app.use(requestTime);
app.get('/', (req: Request, res: Response) => { let responseText = 'Hello World!<br>'; responseText += `<small>Requested at: ${req.requestTime}</small>`; res.send(responseText);});
app.listen(3000);Quando você faz uma solicitação na raiz do aplicativo, o aplicativo agora mostra a marcação de hora da sua solicitação no navegador.
Função Middleware validateCookies
Finalmente, vamos criar uma função de middleware que valida os cookies recebidos e envia uma resposta de 400 se cookies forem inválidos.
Aqui está uma função de exemplo que valida cookies com um serviço assíncrono externo.
async function cookieValidator(cookies) { try { await externallyValidateCookie(cookies.testCookie); } catch { throw new Error('Invalid cookies'); }}async function cookieValidator(cookies: Record<string, string>) { try { await externallyValidateCookie(cookies.testCookie); } catch { throw new Error('Invalid cookies'); }}O middleware ‘validateCookies’ retorna a promessa de que, após a rejeição, irá automaticamente acionar o nosso manipulador de erros. Aqui, usamos o cookie-parser middleware para analisar cookies recebidos do objeto req e passá-los para a nossa função cookieValidator.
const express = require('express');const cookieParser = require('cookie-parser');const cookieValidator = require('./cookieValidator');
const app = express();
async function validateCookies(req, res, next) { await cookieValidator(req.cookies); next();}
app.use(cookieParser());
app.use(validateCookies);
// error handlerapp.use((err, req, res, next) => { res.status(400).send(err.message);});
app.listen(3000);import express from 'express';import cookieParser from 'cookie-parser';import cookieValidator from './cookieValidator';
const app = express();
async function validateCookies(req, res, next) { await cookieValidator(req.cookies); next();}
app.use(cookieParser());
app.use(validateCookies);
// error handlerapp.use((err, req, res, next) => { res.status(400).send(err.message);});
app.listen(3000);import express, { type Express, type Request, type Response, type NextFunction } from 'express';import cookieParser from 'cookie-parser';import cookieValidator from './cookieValidator';
const app: Express = express();
async function validateCookies(req: Request, res: Response, next: NextFunction) { await cookieValidator(req.cookies); next();}
app.use(cookieParser());
app.use(validateCookies);
// error handlerapp.use((err: Error, req: Request, res: Response, next: NextFunction) => { res.status(400).send(err.message);});
app.listen(3000);Observe como next() é chamado depois await cookieValidator(req.cookies). Isto garante que se
cookieValidator resolver, o próximo middleware na pilha será chamado. Se você passar qualquer coisa
para a função next() (exceto a string 'route' ou 'router'), Expresse que a solicitação
atual é um erro e pulará quaisquer funções que ainda não sejam de manipulação de erros e de middleware
.
Como você tem acesso ao objeto de solicitação, o objeto de resposta, a próxima função de middleware na pilha, e todo o nó. s API, as possibilidades com funções de middleware são infinitas.
Para mais informações sobre Express middleware, veja: Usando Express middleware.
middleware configurável
Se precisar de seu middleware para ser configurável, exporte uma função que aceite um objeto de opções ou outros parâmetros, que então retorna a implementação intermediária com base nos parâmetros de entrada.
module.exports = function (options) { return function (req, res, next) { // Implement the middleware function based on the options object next(); };};export default function (options) { return function (req, res, next) { // Implement the middleware function based on the options object next(); };}import { type Request, type Response, type NextFunction } from 'express';
export default function (options: Record<string, unknown>) { return function (req: Request, res: Response, next: NextFunction) { // Implement the middleware function based on the options object next(); };}O middleware agora pode ser usado como mostrado abaixo.
const mw = require('./my-middleware.cjs');
app.use(mw({ option1: '1', option2: '2' }));import mw from './my-middleware.mjs';
app.use(mw({ option1: '1', option2: '2' }));Consulte cookie-session e compression para ver exemplos de intermediário configurável.