Pipeline de Processamento de Requisição e middleware - Node.js
Quando o framework Express recebe uma requisição, ela é passada para um pipeline de processamento. O pipeline é composto por um conjunto de componentes ou middleware, que recebem os dados da requisição e decidem como processá-la.
Assim, no exemplo anterior, o arquivo de aplicação tinha o seguinte código:
const express = require("express");
const app = express();
app.get("/", function(request, response) {
response.send("<h1>Página Principal</h1>");
});
app.get("/about", function(request, response) {
response.send("<h1>Sobre o Site</h1>");
});
app.get("/contact", function(request, response) {
response.send("<h1>Contatos</h1>");
});
app.listen(3000, () => console.log("Servidor iniciado na porta 3000"));
Aqui, o pipeline de processamento consistia em chamadas a app.get()
app.get()
Se necessário, podemos integrar qualquer função middleware no pipeline de processamento da requisição em qualquer etapa. Para isso, usamos o método app.use()
app.js
const express = require("express");
const app = express();
app.use(function(_, _, next) {
console.log("Middleware 1");
next();
});
app.use(function(_, _, next) {
console.log("Middleware 2");
next();
});
app.get("/", function(_, response) {
console.log("Rota /");
response.send("Olá");
});
app.listen(3000, () => console.log("Servidor iniciado em http://localhost:3000"));
A função passada para app.use()
: dados da requisiçãorequest
: objeto para gerenciar a respostaresponse
: próxima função no pipeline de processamentonext
Cada uma das funções middleware apenas exibe uma mensagem no console e, no final, chama a próxima função usando next()
Ao executar a aplicação e acessar o endereço http://localhost:3000/
c:\app> node app.js Middleware 1 Middleware 2 Rota /
No entanto, não é obrigatório chamar todas as funções middleware subsequentes. Podemos interromper o processamento em qualquer etapa:
const express = require("express");
const app = express();
app.use(function(_, _, next) {
console.log("Middleware 1");
next();
});
app.use(function(_, response) {
console.log("Middleware 2");
response.send("Middleware 2");
});
app.get("/", function(_, response) {
console.log("Rota /");
response.send("Olá");
});
app.listen(3000, () => console.log("Servidor iniciado em http://localhost:3000"));
Agora, o processamento termina no Middleware 2, pois neste método ocorre o envio da resposta usando response.send()
next()
c:\app> node app.js Middleware 1 Middleware 2
As funções middleware também podem ser associadas a rotas específicas. Por exemplo:
const express = require("express");
const app = express();
app.use(function(_, _, next) {
console.log("Middleware 1");
next();
});
app.use("/about", function(_, response) {
console.log("About Middleware");
response.send("About Middleware");
});
app.get("/", function(_, response) {
console.log("Rota /");
response.send("Olá");
});
app.listen(3000, () => console.log("Servidor iniciado em http://localhost:3000"));
Neste caso, a segunda função middleware é associada explicitamente à rota /about
http://localhost:3000/about
Por exemplo, ao acessar a rota /about
c:\app> node app.js Middleware 1 About Middleware
Ao acessar a rota /
c:\app> node app.js Middleware 1 Rota /
Exemplo de Middleware
Os middlewares ajudam a executar algumas tarefas que precisam ser feitas antes de enviar a resposta. Uma tarefa comum é o log das requisições.
Por exemplo, alteramos o arquivo app.js
const express = require("express");
const fs = require("fs");
const app = express();
app.use(function(request, response, next) {
const now = new Date();
const hour = now.getHours();
const minutes = now.getMinutes();
const seconds = now.getSeconds();
const data = `${hour}:${minutes}:${seconds} ${request.method} ${request.url} ${request.get("user-agent")}`;
console.log(data);
fs.appendFile("server.log", data + "\n", function(error){
if (error) return console.log(error);
console.log("Gravação no arquivo concluída");
});
next();
});
app.get("/", function(_, response){
response.send("Olá");
});
app.listen(3000, () => console.log("Servidor iniciado em http://localhost:3000"));
Aqui, usando o objeto request, obtemos várias informações sobre a requisição e as adicionamos ao arquivo server.log utilizando o módulo fs