JavaScript

Boas Práticas de Express.js: Roteamento, Middlewares e Estrutura de APIs REST para Times Ágeis

8 min de leitura

Boas Práticas de Express.js: Roteamento, Middlewares e Estrutura de APIs REST para Times Ágeis

Express.js: Fundamentos e Arquitetura Express.js é um framework web minimalista para Node.js que facilita a criação de servidores HTTP e APIs REST. Sua força reside na simplicidade: você constrói apenas o que precisa, sem abstrações desnecessárias. O framework é construído sobre o módulo nativo do Node.js, adicionando camadas de roteamento, middleware e utilitários que aceleram o desenvolvimento. Para começar, instale Express via npm: . Um servidor básico requer apenas alguns comandos para escutar requisições. A arquitetura do Express é orientada por middlewares — funções que processam requisições antes de chegarem à rota final. Compreender esse fluxo é essencial para dominar o framework. Roteamento: O Coração das APIs Definindo Rotas Básicas Rotas definem como sua API responde a diferentes URLs e métodos HTTP. Express fornece métodos diretos para GET, POST, PUT, DELETE e outros. Cada rota é composta por um caminho, um método HTTP e uma função callback que recebe e . Usuário ${req.params.id} atualizado Parâmetros e Query Strings Existem três

<h2>Express.js: Fundamentos e Arquitetura</h2>

<p>Express.js é um framework web minimalista para Node.js que facilita a criação de servidores HTTP e APIs REST. Sua força reside na simplicidade: você constrói apenas o que precisa, sem abstrações desnecessárias. O framework é construído sobre o módulo nativo <code>http</code> do Node.js, adicionando camadas de roteamento, middleware e utilitários que aceleram o desenvolvimento.</p>

<p>Para começar, instale Express via npm: <code>npm install express</code>. Um servidor básico requer apenas alguns comandos para escutar requisições. A arquitetura do Express é orientada por middlewares — funções que processam requisições antes de chegarem à rota final. Compreender esse fluxo é essencial para dominar o framework.</p>

<pre><code class="language-javascript">const express = require(&#039;express&#039;);

const app = express();

app.listen(3000, () =&gt; {

console.log(&#039;Servidor rodando na porta 3000&#039;);

});</code></pre>

<h2>Roteamento: O Coração das APIs</h2>

<h3>Definindo Rotas Básicas</h3>

<p>Rotas definem como sua API responde a diferentes URLs e métodos HTTP. Express fornece métodos diretos para GET, POST, PUT, DELETE e outros. Cada rota é composta por um caminho, um método HTTP e uma função callback que recebe <code>request</code> e <code>response</code>.</p>

<pre><code class="language-javascript">const express = require(&#039;express&#039;);

const app = express();

// GET

app.get(&#039;/usuarios&#039;, (req, res) =&gt; {

res.json({ message: &#039;Lista de usuários&#039; });

});

// POST

app.post(&#039;/usuarios&#039;, (req, res) =&gt; {

res.status(201).json({ message: &#039;Usuário criado&#039; });

});

// PUT

app.put(&#039;/usuarios/:id&#039;, (req, res) =&gt; {

res.json({ message: Usuário ${req.params.id} atualizado });

});

// DELETE

app.delete(&#039;/usuarios/:id&#039;, (req, res) =&gt; {

res.status(204).send();

});

app.listen(3000);</code></pre>

<h3>Parâmetros e Query Strings</h3>

<p>Existem três formas principais de capturar dados: parâmetros de rota (<code>req.params</code>), query strings (<code>req.query</code>) e body (<code>req.body</code>). Parâmetros de rota são valores obrigatórios na URL; query strings são opcionais e vêm após <code>?</code>. O body contém dados estruturados enviados em POST/PUT.</p>

<pre><code class="language-javascript">// Parâmetro de rota: /produtos/123

app.get(&#039;/produtos/:id&#039;, (req, res) =&gt; {

console.log(req.params.id); // &quot;123&quot;

res.json({ id: req.params.id });

});

// Query string: /produtos?categoria=eletrônicos&amp;preco=100

app.get(&#039;/produtos&#039;, (req, res) =&gt; {

console.log(req.query.categoria); // &quot;eletrônicos&quot;

console.log(req.query.preco); // &quot;100&quot;

res.json({ categoria: req.query.categoria });

});

// Body (requer middleware express.json())

app.post(&#039;/produtos&#039;, (req, res) =&gt; {

console.log(req.body.nome); // dados do formulário

res.json({ received: req.body });

});</code></pre>

<h2>Middlewares: Processamento em Cadeia</h2>

<p>Middlewares são funções executadas entre a requisição e a resposta. Cada middleware pode modificar <code>req</code> e <code>res</code>, passar o controle para o próximo middleware via <code>next()</code> ou encerrar a requisição com uma resposta. Essa arquitetura permite separar responsabilidades como autenticação, validação e logging.</p>

<pre><code class="language-javascript">const express = require(&#039;express&#039;);

const app = express();

// Middleware global

app.use(express.json()); // Parse JSON automaticamente

// Middleware customizado de logging

app.use((req, res, next) =&gt; {

console.log(${new Date().toISOString()} - ${req.method} ${req.path});

next(); // Passa para o próximo middleware

});

// Middleware de autenticação

const verificarToken = (req, res, next) =&gt; {

const token = req.headers.authorization;

if (!token) {

return res.status(401).json({ erro: &#039;Token ausente&#039; });

}

req.usuario = { id: 1, nome: &#039;João&#039; }; // Simulado

next();

};

// Usando middleware em rota específica

app.get(&#039;/dados-privados&#039;, verificarToken, (req, res) =&gt; {

res.json({ mensagem: Olá, ${req.usuario.nome} });

});

// Middleware de erro (deve ser o último)

app.use((err, req, res, next) =&gt; {

console.error(err.stack);

res.status(500).json({ erro: &#039;Erro interno do servidor&#039; });

});

app.listen(3000);</code></pre>

<h2>Estrutura de APIs REST Profissional</h2>

<h3>Organização em Camadas</h3>

<p>Uma API REST profissional separava responsabilidades em camadas: rotas, controllers e models. As rotas apenas mapeiam URLs para funções; controllers contêm a lógica de negócio; models representam dados. Essa estrutura facilita testes, manutenção e escalabilidade.</p>

<pre><code class="language-javascript">// routes/usuarios.js

const express = require(&#039;express&#039;);

const router = express.Router();

const usuariosController = require(&#039;../controllers/usuariosController&#039;);

router.get(&#039;/&#039;, usuariosController.listar);

router.post(&#039;/&#039;, usuariosController.criar);

router.get(&#039;/:id&#039;, usuariosController.obter);

router.put(&#039;/:id&#039;, usuariosController.atualizar);

router.delete(&#039;/:id&#039;, usuariosController.deletar);

module.exports = router;

// controllers/usuariosController.js

const usuarios = []; // Simulado

exports.listar = (req, res) =&gt; {

res.json(usuarios);

};

exports.criar = (req, res) =&gt; {

const novoUsuario = { id: Date.now(), ...req.body };

usuarios.push(novoUsuario);

res.status(201).json(novoUsuario);

};

exports.obter = (req, res) =&gt; {

const usuario = usuarios.find(u =&gt; u.id == req.params.id);

if (!usuario) return res.status(404).json({ erro: &#039;Não encontrado&#039; });

res.json(usuario);

};

exports.atualizar = (req, res) =&gt; {

const usuario = usuarios.find(u =&gt; u.id == req.params.id);

if (!usuario) return res.status(404).json({ erro: &#039;Não encontrado&#039; });

Object.assign(usuario, req.body);

res.json(usuario);

};

exports.deletar = (req, res) =&gt; {

const index = usuarios.findIndex(u =&gt; u.id == req.params.id);

if (index === -1) return res.status(404).json({ erro: &#039;Não encontrado&#039; });

usuarios.splice(index, 1);

res.status(204).send();

};

// app.js

const express = require(&#039;express&#039;);

const usuariosRouter = require(&#039;./routes/usuarios&#039;);

const app = express();

app.use(express.json());

app.use(&#039;/api/usuarios&#039;, usuariosRouter);

app.listen(3000);</code></pre>

<h3>Tratamento de Erros e Validação</h3>

<p>Toda API robusta precisa validar dados recebidos e comunicar erros claramente. Use bibliotecas como <code>joi</code> ou <code>express-validator</code> para validação declarativa. Sempre retorne status HTTP apropriados: 400 para dados inválidos, 404 para não encontrado, 500 para erro do servidor.</p>

<pre><code class="language-javascript">const { body, validationResult } = require(&#039;express-validator&#039;);

app.post(&#039;/usuarios&#039;,

body(&#039;email&#039;).isEmail(),

body(&#039;idade&#039;).isInt({ min: 18 }),

(req, res) =&gt; {

const erros = validationResult(req);

if (!erros.isEmpty()) {

return res.status(400).json({ erros: erros.array() });

}

// Lógica de criação

res.status(201).json({ success: true });

}

);</code></pre>

<h2>Conclusão</h2>

<p>Os três pilares do Express.js — <strong>roteamento bem organizado</strong>, <strong>middlewares para separar responsabilidades</strong> e <strong>estrutura em camadas</strong> — formam a base de qualquer API REST profissional. Domine o fluxo de requisição-resposta, use middlewares para código limpo e escalável, e organize suas rotas e controllers de forma lógica. Esses fundamentos aplicados transformam um projeto caótico em uma aplicação mantível e testável.</p>

<h2>Referências</h2>

<ul>

<li><a href="https://expressjs.com/" target="_blank" rel="noopener noreferrer">Documentação Oficial Express.js</a></li>

<li><a href="https://github.com/goldbergyoni/nodebestpractices" target="_blank" rel="noopener noreferrer">Node.js Best Practices</a></li>

<li><a href="https://restfulapi.net/" target="_blank" rel="noopener noreferrer">RESTful API Design Guidelines</a></li>

<li><a href="https://expressjs.com/en/guide/using-middleware.html" target="_blank" rel="noopener noreferrer">Express Middleware Guide</a></li>

<li><a href="https://express-validator.github.io/docs/" target="_blank" rel="noopener noreferrer">Express-Validator Documentation</a></li>

</ul>

Comentários

Mais em JavaScript

Guia Completo de Interfaces e Type Aliases em TypeScript na Prática
Guia Completo de Interfaces e Type Aliases em TypeScript na Prática

Fundamentos: Type Aliases vs Interfaces Type Aliases e Interfaces são dois me...

NPM e Package.json: Gerenciamento de Dependências em JavaScript na Prática
NPM e Package.json: Gerenciamento de Dependências em JavaScript na Prática

O que é NPM e por que você precisa dominar NPM (Node Package Manager) é o ger...

Higher-Order Functions em JavaScript: map, filter, reduce e Composição na Prática
Higher-Order Functions em JavaScript: map, filter, reduce e Composição na Prática

O que são Higher-Order Functions? Higher-Order Functions (HOF) são funções qu...