Node.js: Rotas e Middleware
Última atualização: 2026-08-26
O projeto de API do Charlie tinha, inicialmente, apenas cinco rotas, todas escritas em app.js, o que ainda era bastante claro. Dois meses depois, o número de rotas havia crescido para 30, e o arquivo ultrapassou 500 linhas — demorava uma eternidade para fazer uma única alteração em um endpoint da API. A equipe decidiu usar express.Router() para dividir as rotas em módulos — as rotas de usuários foram para users.js, as de autenticação para auth.js e o middleware de log personalizado foi movido para um arquivo separado. Após a divisão, cada arquivo passou a ter uma única responsabilidade, e a eficiência da manutenção melhorou significativamente.
Você aprenderá:
- Use
express.Router()para dividir rotas modulares - Como ler parâmetros de rota, strings de consulta e corpos de solicitação
- Criação de middleware personalizado e o mecanismo
next() - Integração de middleware de terceiros (CORS / Morgan / Helmet)
- Projeto de middleware para tratamento de erros e tratamento global de erros
1. express.Router() – Roteamento modular
À medida que o número de rotas aumenta, colocar todas as rotas em app.js pode resultar em arquivos muito grandes e dificultar a colaboração. express.Router() permite que você crie instâncias independentes de rotas e, em seguida, as monte em um prefixo de caminho específico em seu aplicativo.
| Recurso | Rotas definidas diretamente no aplicativo | Roteamento modular por meio do módulo Router |
|---|---|---|
| Organização de arquivos | Tudo no app.js | Dividido em arquivos separados por módulo |
| Prefixo do caminho | Especifique o caminho completo para cada raiz | Defina um prefixo uniforme ao montar |
| Colaboração em equipe | Vários usuários editando o mesmo arquivo | Manutenção independente de cada módulo |
| Reutilização | Baixa | Alta; pode ser reutilizado em diferentes projetos |
▶ Exemplo: Criação de um módulo de roteamento de usuários independente
// routes/users.js
const express = require('express');
const router = express.Router();
router.get('/', (req, res) => {
res.json({ users: ['Alice', 'Bob'] });
});
router.get('/:id', (req, res) => {
res.json({ user: req.params.id });
});
module.exports = router;
▶ Exemplo: Montagem de um módulo de rota no arquivo app.js
// app.js
const express = require('express');
const app = express();
const userRouter = require('./routes/users');
app.use('/users', userRouter);
app.listen(3000, () => {
console.log('Server running on port 3000');
});
A visita a /users corresponde a router.get('/'), e a visita a /users/42 corresponde a router.get('/:id').
2. Parâmetros de rota, strings de consulta e corpos de solicitação
O Express oferece três formas de receber dados de clientes, cada uma adequada a diferentes cenários.
| Fonte de dados | Como acessar | Exemplo de URL | Usos típicos |
|---|---|---|---|
| Parâmetros de roteamento | req.params |
/users/42 |
Identifica um recurso específico |
| String de consulta | req.query |
/users?role=admin |
Filtrar, Ordenar, Pesquisar |
| Corpo da solicitação | req.body |
Corpo da solicitação POST | Enviar formulário/dados JSON |
▶ Exemplo: Parâmetro de rota :id
app.get('/products/:id', (req, res) => {
const productId = req.params.id;
res.json({ productId });
});
▶ Exemplo: Consulta string req.query
app.get('/products', (req, res) => {
const { category, sort, page } = req.query;
res.json({ category, sort, page: page || 1 });
});
Acesse /products?category=electronics&sort=price&page=2, req.query e { category: 'electronics', sort: 'price', page: '2' }.
▶ Exemplo: Corpo da solicitação req.body e express.json()
app.use(express.json());
app.post('/products', (req, res) => {
const { name, price } = req.body;
res.status(201).json({ name, price });
});
Observação: Os valores de
req.queryereq.paramssão, ambos, cadeias de caracteres e devem ser convertidos manualmente em números.
3. Noções básicas sobre middleware e o mecanismo next()
O middleware é um conceito fundamental do Express — toda solicitação passa por uma cadeia de middleware, e cada função de middleware pode ler a solicitação, modificar a resposta ou passar o controle para a próxima função de middleware.
graph LR A[Request] --> B[morgan Log] B --> C[express.json Analysis] C --> D[Custom auth Middleware] D --> E[Route Handling Functions] E --> F[Response] D -->|next error| G[Error-handling middleware]
▶ Exemplo: O middleware personalizado mais simples
function logger(req, res, next) {
console.log(`${req.method} ${req.url} - ${new Date().toISOString()}`);
next();
}
app.use(logger);
| Regra | Descrição |
|---|---|
next() deve ser chamado |
Caso contrário, a solicitação será suspensa e o cliente nunca receberá uma resposta |
| A ordem de chamada é a ordem de execução | O middleware registrado primeiro é executado primeiro |
app.use() Aplica-se globalmente |
app.use('/api', ...) Aplica-se apenas ao caminho /api |
next('route') |
Ignorar o middleware restante para a rota atual |
4. Integração com middleware de terceiros
A comunidade oferece uma ampla variedade de middleware pronto para uso, que pode ser ativado com uma única linha de código após a instalação.
| Middleware | Finalidade | Comando de instalação |
|---|---|---|
| cors | Resolução de problemas com solicitações entre origens | npm install cors |
| morgan | Registro de solicitações HTTP | npm install morgan |
| capacete | Configurar um capacete de resposta de segurança | npm install helmet |
| express-rate-limit | Limite de taxa de solicitações | npm install express-rate-limit |
| cookie-parser | Analisar cookies | npm install cookie-parser |
▶ Exemplo: Integração de CORS, Morgan e Helmet
const cors = require('cors');
const morgan = require('morgan');
const helmet = require('helmet');
app.use(helmet());
app.use(cors());
app.use(morgan('combined'));
app.use(express.json());
Observação: Recomenda-se colocar o middleware relacionado à segurança (Helmet) em primeiro lugar, seguido imediatamente pelo middleware de registro de logs.
5. Middleware para tratamento de erros
Convenção Express: Uma função com quatro parâmetros (err, req, res, next) é um middleware de tratamento de erros. Sempre que algum middleware chama next(err), ele ignora o middleware regular subsequente e prossegue diretamente para o middleware de tratamento de erros.
| Item de comparação | Middleware padrão | Middleware de tratamento de erros |
|---|---|---|
| Número de parâmetros | 3 (req, res, next) | 4 (err, req, res, next) |
| Método de acionamento | Executar sequencialmente à medida que as solicitações chegam | next(err) Acionamento |
| Local de inscrição | Qualquer local | Deve ser colocado por último |
| Pode haver mais de um? | Sim | Sim, executados em ordem |
▶ Exemplo: Middleware de tratamento global de erros
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(err.status || 500).json({
error: err.message || 'Internal Server Error'
});
});
▶ Exemplo: Gerando um error em uma route
app.get('/admin', (req, res, next) => {
const err = new Error('Access denied');
err.status = 403;
next(err);
});
6. Mermaid: Estrutura modular de roteamento do roteador
graph TD APP[app.js] --> UR["/users → userRouter"] APP --> AR["/auth → authRouter"] APP --> MW["middleware/logger.js"] UR --> U1["GET / → User List"] UR --> U2["GET /:id → User Details"] UR --> U3["POST / → Create a User"] AR --> A1["POST /login → Log In"] AR --> A2["POST /register → Register"] MW --> ML["Logging Middleware"]
7. Exemplo abrangente: API de roteamento modular
Neste exemplo, o middleware de roteamento do usuário, o de autenticação e o de registro de log são divididos em arquivos separados e, por fim, integrados ao app.js.
▶ Exemplo: middleware/logger.js — Middleware de registro personalizado
function logger(req, res, next) {
const start = Date.now();
res.on('finish', () => {
const duration = Date.now() - start;
console.log(`${req.method} ${req.originalUrl} ${res.statusCode} ${duration}ms`);
});
next();
}
module.exports = logger;
▶ Exemplo: routes/users.js — Módulo de rotas do usuário
const express = require('express');
const router = express.Router();
let users = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' }
];
router.get('/', (req, res) => {
res.json(users);
});
router.get('/:id', (req, res, next) => {
const user = users.find(u => u.id === parseInt(req.params.id));
if (!user) {
const err = new Error('User not found');
err.status = 404;
return next(err);
}
res.json(user);
});
router.post('/', (req, res) => {
const { name } = req.body;
if (!name) {
return res.status(400).json({ error: 'Name is required' });
}
const newUser = { id: users.length + 1, name };
users.push(newUser);
res.status(201).json(newUser);
});
module.exports = router;
▶ Exemplo: routes/auth.js — Módulo de rotas de autenticação
const express = require('express');
const router = express.Router();
router.post('/login', (req, res) => {
const { username, password } = req.body;
if (!username || !password) {
return res.status(400).json({ error: 'Username and password required' });
}
res.json({ message: 'Login successful', token: 'mock-jwt-token' });
});
router.post('/register', (req, res) => {
const { username, email, password } = req.body;
if (!username || !email || !password) {
return res.status(400).json({ error: 'All fields are required' });
}
res.status(201).json({ message: 'Registration successful' });
});
module.exports = router;
▶ Exemplo: app.js — Ponto de entrada da integração
const express = require('express');
const helmet = require('helmet');
const cors = require('cors');
const morgan = require('morgan');
const logger = require('./middleware/logger');
const userRouter = require('./routes/users');
const authRouter = require('./routes/auth');
const app = express();
app.use(helmet());
app.use(cors());
app.use(morgan('combined'));
app.use(express.json());
app.use(logger);
app.use('/users', userRouter);
app.use('/auth', authRouter);
app.use((req, res) => {
res.status(404).json({ error: 'Route not found' });
});
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(err.status || 500).json({
error: err.message || 'Internal Server Error'
});
});
app.listen(3000, () => {
console.log('Server running on port 3000');
});
Executar teste:
node app.js
Server running on port 3000
GET /users 200 3ms
GET /users/1 200 2ms
POST /auth/login 200 5ms
❓ Perguntas Frequentes
P: O que acontece se
next()não for chamado? R: A solicitação será suspensa, e o cliente nunca receberá uma resposta. É necessário chamarnext()no middleware para passar o controle, ou usar métodos comores.end()oures.json()para encerrar diretamente a resposta.
P: Qual é a diferença entre parâmetros de rota e parâmetros de consulta? R: Os parâmetros de rota fazem parte do caminho da URL, como o 42 em /users/:id, que pode ser recuperado usando req.params.id; os parâmetros de consulta são pares chave-valor que vêm após o ?, como em /users?role=admin, que podem ser recuperados usando req.query.role. Os primeiros identificam recursos, enquanto os segundos filtram recursos.
P: A ordem em que o middleware é registrado é importante? R: É muito importante. O Express executa o middleware na ordem em que ele é registrado. Por exemplo,
express.json()deve ser registrado antes de qualquer rota que precise lerreq.body; caso contrário,req.bodyseráundefined.
P: Como faço para implementar o tratamento global de erros? R: Defina uma função com quatro argumentos (err, req, res, next) e registre-a com
app.use()após todas as rotas e middlewares. Qualquer middleware que chamarnext(err)será encaminhado para esse manipulador.
P: Que problema o middleware CORS resolve? R: A política de mesma origem do navegador bloqueia solicitações entre origens. O middleware CORS adiciona campos como
Access-Control-Allow-Originaos cabeçalhos de resposta, permitindo que aplicativos front-end de origens especificadas acessem a API.
P: Qual é a diferença entre
express.Router()e usarapp.get()diretamente? R:Routercria uma instância de roteador independente que pode ser montada em qualquer prefixo de rota, tornando-a adequada para modularização;app.get()é registrado diretamente na instância da aplicação, tornando-o adequado para projetos simples. Ambos são funcionalmente equivalentes; a diferença está na forma como são organizados.
P: Como posso modificar o objeto
reqem um middleware para passar dados para o processamento subsequente? R: Basta atribuir propriedades diretamente aoreq, comoreq.user = { id: 1 }. Os middlewares e rotas subsequentes poderão então acessar esses dados por meio doreq.user. Esse é um padrão comum para a comunicação entre middlewares no Express.
📖 Resumo
- 1 express.Router(): Conceitos básicos e uso do roteamento modular
- 2 Conceitos básicos e uso de parâmetros de rota, strings de consulta e corpos de solicitação
- 3 Conceitos-chave e uso dos fundamentos do middleware e do mecanismo next()
- 4 Conceitos fundamentais e métodos de uso para integração de middleware de terceiros
- 5 Conceitos fundamentais e uso de middleware para tratamento de erros
- 6 Mermaid: Conceitos básicos e uso da estrutura de roteamento modular no módulo do roteador
- 7 Exemplo abrangente: conceitos básicos e uso da API de roteamento modular
📝 Exercícios
- Conclua todos os exemplos de código desta lição e certifique-se de que cada um deles seja executado corretamente.
- Modifique o exemplo completo e adicione suas próprias extensões
- Analise a documentação oficial, identifique 1 ou 2 APIs que não foram abordadas nesta aula e escreva um código de teste para elas.
- Reflexão: Como você aplicaria o que aprendeu nesta aula a um projeto do mundo real?
- Tente combinar o que você aprendeu nesta aula com o conteúdo das aulas anteriores para criar um pequeno projeto.