Menu

Middleware no Express: como o next() funciona, com exemplos

Um middleware do Express é uma função (req, res, next) que roda antes do seu route handler. Ele pode ler ou alterar a requisição, encerrá-la com uma resposta ou chamar next() para passá-la adiante.

Esta página tem editores executáveis. Edite, execute e veja a saída na hora.

Middleware no Express é uma função com a assinatura (req, res, next) que roda entre o momento em que a requisição chega e o momento em que a resposta é enviada. Cada middleware pode ler ou alterar req e res, encerrar a requisição enviando uma resposta, ou chamar next() para entregar a requisição à próxima função da fila. app.use(fn) adiciona um middleware para todas as requisições, e o Express roda tudo na ordem em que você registrou.

O Console registra os três passos em ordem a cada requisição, e a rota lê req.startedAt, uma propriedade que o logger adicionou. Envie GET /missing: os dois middlewares ainda registram, porque app.use() casa com qualquer caminho, e depois o Express responde 404, já que nenhuma rota correspondeu.

Esquecer o next()

Um middleware que nem envia resposta nem chama next() deixa a requisição pendurada. O cliente espera até dar timeout, e nada aparece nos logs, o que faz deste um bug de middleware comum. Apague next(); do logger acima e envie GET / de novo: a requisição nunca recebe resposta.

A regra é simples: todo caminho dentro de um middleware termina em exatamente uma destas opções:

  • next() para continuar,
  • next(err) para pular para o error handler (veja tratamento de erros no Express),
  • uma resposta como res.json() ou res.status(401).send().

Chamar next() depois de enviar uma resposta também é bug. O próximo handler tenta enviar uma segunda resposta e o Express lança ERR_HTTP_HEADERS_SENT. Escreva return res.status(401).json(...) para a função parar ali.

Um auth check que barra a requisição

Um middleware que rejeita uma requisição envia a resposta ele mesmo e nunca chama next(). Passe ele como argumento extra de uma rota para proteger só aquela rota:

A primeira requisição recebe 401 com {"error":"Missing or wrong API key"}. Adicione o header x-api-key: secret123 na barra de requisição e envie de novo: agora a resposta é {"users":42,"caller":"reporting-app"}. /public nunca roda a verificação.

Onde o middleware roda

Você escreveRoda para
app.use(fn)Toda requisição, todo método
app.use('/api', fn)Caminhos que começam com /api
app.get('/admin', fn, handler)Só GET /admin, antes do handler
router.use(fn)Todas as rotas daquele router

A ordem faz parte do significado. Um logger registrado depois das rotas nunca registra as requisições que essas rotas responderam, porque uma rota que envia uma resposta não chama next(). Registre primeiro os middlewares do app inteiro, como logging, parse do body e CORS, depois as rotas, depois os handlers de 404 e de erro.

Middleware nativo

O Express traz algumas funções de middleware que você adiciona com app.use(). Os body parsers preenchem req.body; sem eles, ele é undefined.

MiddlewareO que faz
express.json()Interpreta bodies JSON (Content-Type: application/json)
express.urlencoded()Interpreta envios de formulário HTML (name=Ada&age=36)
express.text()Coloca um body de texto puro em req.body como string
express.static('public')Serve arquivos de uma pasta

Envie POST /echo com o body {"name": "Ada"} e a resposta inclui "body":{"name":"Ada"}. Remova a linha do express.json(), envie de novo, e body some da resposta: req.body é undefined, e JSON.stringify deixa valores undefined de fora. Pacotes como cors, helmet e morgan também são middleware: você faz npm install e passa para app.use() do mesmo jeito. A página do express.static cobre como servir arquivos.

Erros comuns

Chamar o middleware em vez de passá-lo. app.use(logger()) roda o logger uma vez na inicialização e registra o valor que ele retorna. Escreva app.use(logger). (express.json() tem parênteses porque retorna uma função de middleware.)

Adicionar o body parser depois das rotas. As rotas rodam primeiro e veem req.body como undefined.

Esperar que app.use('/admin', fn) case com um caminho só. Ele também roda para /admin/users e qualquer outro caminho abaixo de /admin, para todos os métodos. Para proteger uma única rota, passe o middleware para app.get('/admin', fn, handler).

Perguntas frequentes

Qual a diferença entre middleware e route handler?

Tecnicamente, nenhuma: os dois são funções de (req, res, next). Por convenção, um route handler encerra a requisição com uma resposta, enquanto um middleware geralmente faz um trabalho comum e chama next().

Um middleware pode ser async?

Sim. No Express 5, um middleware async que lança erro ou retorna uma promise rejeitada envia o erro para o seu error handler automaticamente. Dê await no que precisar e depois chame next().

O que faz next('route')?

Ele pula os handlers restantes da rota atual e vai para a próxima rota que corresponde. Só funciona em handlers adicionados com app.get(), app.post() e as outras funções de método, não em app.use().

Como pulo um middleware em uma rota específica?

Registre essa rota antes do middleware, para ela responder primeiro, ou confira o caminho dentro do middleware (if (req.path === '/health') return next();). Aplicar o middleware por router ou por rota, em vez de no app inteiro, muitas vezes resolve.

Ilustração das linguagens de programação do Coddy

Aprenda a programar com o Coddy

Começar