
outubro 13, 2025
0
Desvendando o Express: pipeline de middlewares, roteamento modular, 404 e error handling
Resumo rápido: entenda o ciclo req → middleware → rota → resposta, organize a estrutura do projeto e implemente parsers, sub-routers, 404 e tratamento central de erros com exemplos práticos.
Por que usar Express para começar?
Express é um microframework: entrega o essencial e deixa você compor funcionalidades com middlewares e rotas. Isso facilita começar pequeno e evoluir com segurança.
Setup mínimo (pronto para evoluir)
mkdir meu-app-express && cd meu-app-express
npm init -y
npm i express
npm i -D nodemon
package.json (script de dev):
{
"type": "module",
"scripts": { "dev": "nodemon src/server.js" },
"dependencies": { "express": "^4.19.0" }
}
Estrutura sugerida:
src/
server.js
app.js
routes/
index.js
users.js
middlewares/
logger.js
public/
O ciclo de requisição no Express
- Chegada do request
- Pilha de middlewares (log, parse, auth…)
- Roteador decide qual handler atende
- Resposta (ou delega a
next()) - Tratador de erros padroniza falhas
src/app.js
import express from "express";
import logger from "./middlewares/logger.js";
import indexRouter from "./routes/index.js";
import usersRouter from "./routes/users.js";
const app = express();
// Middlewares globais
app.use(logger);
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(express.static("public"));
// Rotas
app.use("/", indexRouter);
app.use("/users", usersRouter);
// 404 (depois das rotas)
app.use((req, res) => {
res.status(404).json({ error: "Rota não encontrada" });
});
// Handler central de erros (4 parâmetros)
app.use((err, req, res, next) => {
console.error("[ERRO]", err);
res.status(err.status || 500).json({
error: err.message || "Erro interno do servidor",
});
});
export default app;
src/server.js
import app from "./app.js";
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Servidor em http://localhost:${PORT}`);
});
Middlewares: pequenas funções, grande poder
Um middleware recebe (req, res, next). Ele pode inspecionar/alterar req e res, responder imediatamente ou encadear com next().
src/middlewares/logger.js
export default function logger(req, res, next) {
const start = Date.now();
res.on("finish", () => {
const ms = Date.now() - start;
console.log(`${req.method} ${req.originalUrl} → ${res.statusCode} (${ms}ms)`);
});
next();
}
Boas práticas:
- Middlewares curtos e focados;
- Ordem importa (ex.:
express.json()antes de rotas que usamreq.body); - Erros vão para o handler central chamando
next(err).
Roteamento claro com sub-routers
Separe por domínio para ganhar legibilidade e testes mais simples.
src/routes/index.js
import { Router } from "express";
const router = Router();
router.get("/", (req, res) => {
res.json({ ok: true, message: "API online 👋" });
});
export default router;
src/routes/users.js
import { Router } from "express";
const router = Router();
// GET /users
router.get("/", (req, res) => {
res.json([{ id: 1, name: "Ada" }, { id: 2, name: "Linus" }]);
});
// GET /users/:id
router.get("/:id", (req, res, next) => {
const { id } = req.params;
if (id === "0") return next({ status: 400, message: "ID inválido" });
res.json({ id, name: "Usuário Exemplo" });
});
// POST /users
router.post("/", (req, res) => {
const { name } = req.body;
res.status(201).json({ id: 3, name });
});
export default router;
404 e erros: respostas consistentes
- 404: defina após as rotas para capturar caminhos não mapeados.
- Erros: um único handler central padroniza mensagens e status.
- Retorne JSON limpo (objetos) e status codes corretos (
201para criação,400inválido,404não encontrado,500interno).
Estáticos e (se precisar) views
app.use(express.static("public"))serve assets sem esforço.- Se usar SSR (Pug/EJS), mantenha routers de página separados das rotas de API.
Teste rápido (curl/HTTP client)
GET /→{ ok: true, ... }GET /users→ listaGET /users/0→400(testa o handler de erro)POST /users { "name": "Grace" }→201 Created