Como integrar validação de CPF em Express.js com middleware customizado

Aprenda a integrar a API de consulta de CPF da CPFHub.io em Express.js criando middlewares customizados para validação, cache e rate limiting.

Redação CPFHub.io
Redação CPFHub.io
··7 min de leitura
Como integrar validação de CPF em Express.js com middleware customizado

O Express.js é o framework Node.js mais utilizado no mundo, conhecido pela sua simplicidade e flexibilidade. Para integrar a API de CPF da CPFHub.io, você monta uma cadeia de middlewares independentes: um valida o formato do CPF, outro serve o cache, outro chama a API com fetch nativo e um último aplica rate limiting local. A API responde em ~900ms e usa autenticação via header x-api-key — quando o limite do plano é atingido, ela cobra R$0,15 por consulta excedente sem bloquear a requisição.


1. Pré-requisitos

  • Node.js 18+ instalado (para suporte nativo a fetch).

  • Express.js instalado (npm install express).

  • Uma conta na CPFHub.io


2. Estrutura do projeto

cpf-validator/
    ├── middlewares/
    │ ├── validateCpfFormat.js
    │ ├── cpfLookup.js
    │ ├── cpfCache.js
    │ └── rateLimiter.js
    ├── app.js
    ├── package.json
    └── .env

3. Variáveis de ambiente

Crie o arquivo .env:

CPFHUB_API_KEY=SUA_CHAVE_DE_API
CPFHUB_BASE_URL=https://api.cpfhub.io
CPFHUB_TIMEOUT=5000
PORT=3000

Instale o dotenv:

npm install express dotenv

4. Middleware de validação de formato

O primeiro middleware válida se o CPF tem o formato correto antes de prosseguir:

// middlewares/validateCpfFormat.js

function validateCpfFormat(req, res, next) {
    const cpf = req.params.cpf?.replace(/\D/g, '');

    if (!cpf || cpf.length !== 11) {
    return res.status(400).json({
    error: 'CPF deve conter exatamente 11 dígitos numéricos'
    });
    }

    // Rejeitar CPFs com todos os dígitos iguais
    if (/^(\d)\1{10}$/.test(cpf)) {
    return res.status(400).json({
    error: 'CPF inválido'
    });
    }

    req.cpf = cpf;
    next();
}

module.exports = validateCpfFormat;

5. Middleware de consulta à API

O segundo middleware consulta a API da CPFHub.io e anexa o resultado ao objeto de request:

// middlewares/cpfLookup.js

async function cpfLookup(req, res, next) {
    const cpf = req.cpf;
    const apiKey = process.env.CPFHUB_API_KEY;
    const baseUrl = process.env.CPFHUB_BASE_URL;
    const timeout = parseInt(process.env.CPFHUB_TIMEOUT || '5000', 10);

    const controller = new AbortController();
    const timeoutId = setTimeout(() => controller.abort(), timeout);

    try {
    const response = await fetch(`${baseUrl}/cpf/${cpf}`, {
    method: 'GET',
    headers: {
    'x-api-key': apiKey,
    'Accept': 'application/json'
    },
    signal: controller.signal
    });

    clearTimeout(timeoutId);

    if (!response.ok) {
    const mensagens = {
    400: 'CPF com formato inválido',
    401: 'Chave de API inválida ou ausente',
    404: 'CPF não encontrado'
    };

    return res.status(response.status).json({
    error: mensagens[response.status] || `Erro HTTP ${response.status}`
    });
    }

    const data = await response.json();
    req.cpfData = data;
    next();
    } catch (error) {
    clearTimeout(timeoutId);

    if (error.name === 'AbortError') {
    return res.status(504).json({ error: 'Timeout na consulta de CPF' });
    }

    return res.status(502).json({ error: 'Falha na conexão com a API de CPF' });
    }
}

module.exports = cpfLookup;

6. Middleware de cache

Para evitar consultas duplicadas e economizar requisições do plano:

// middlewares/cpfCache.js

const cache = new Map();
const CACHE_TTL = 60 * 60 * 1000; // 1 hora em milissegundos

function cpfCache(req, res, next) {
    const cpf = req.cpf;
    const cached = cache.get(cpf);

    if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
    return res.json(cached.data);
    }

    // Interceptar a resposta para salvar no cache
    const originalJson = res.json.bind(res);
    res.json = function (data) {
    if (res.statusCode === 200 && data.success) {
    cache.set(cpf, { data, timestamp: Date.now() });
    }
    return originalJson(data);
    };

    next();
}

// Limpar entradas expiradas periodicamente
setInterval(() => {
    const now = Date.now();
    for (const [key, value] of cache.entries()) {
    if (now - value.timestamp > CACHE_TTL) {
    cache.delete(key);
    }
    }
}, 5 * 60 * 1000); // A cada 5 minutos

module.exports = cpfCache;

7. Middleware de rate limiting

// middlewares/rateLimiter.js

const requests = new Map();

function rateLimiter(windowMs = 60000, maxRequests = 30) {
    return function (req, res, next) {
    const ip = req.ip;
    const now = Date.now();
    const entry = requests.get(ip);

    if (entry && now - entry.timestamp < windowMs) {
    if (entry.count >= maxRequests) {
    return res.status(429).json({
    error: 'Limite de requisições excedido. Tente novamente em breve.'
    });
    }
    entry.count++;
    } else {
    requests.set(ip, { count: 1, timestamp: now });
    }

    next();
    };
}

module.exports = rateLimiter;

8. Aplicação completa

// app.js
require('dotenv').config();
const express = require('express');
const validateCpfFormat = require('./middlewares/validateCpfFormat');
const cpfCache = require('./middlewares/cpfCache');
const cpfLookup = require('./middlewares/cpfLookup');
const rateLimiter = require('./middlewares/rateLimiter');

const app = express();
const PORT = process.env.PORT || 3000;

// Middleware global de rate limiting
app.use('/api', rateLimiter(60000, 30));

// Rota de consulta de CPF com pipeline de middlewares
app.get(
    '/api/cpf/:cpf',
    validateCpfFormat,
    cpfCache,
    cpfLookup,
    (req, res) => {
    res.json(req.cpfData);
    }
);

// Health check
app.get('/health', (req, res) => {
    res.json({ status: 'ok' });
});

app.listen(PORT, () => {
    console.log(`Servidor rodando na porta ${PORT}`);
});

A cadeia de middlewares executa na ordem: rate limiting, validação de formato, cache, consulta à API, resposta.


9. Teste com cURL

node app.js
curl -X GET http://localhost:3000/api/cpf/12345678900 \
    -H "Accept: application/json"

Resposta esperada:

{
    "success": true,
    "data": {
    "cpf": "12345678900",
    "name": "João da Silva",
    "nameUpper": "JOÃO DA SILVA",
    "gender": "M",
    "birthDate": "15/06/1990",
    "day": 15,
    "month": 6,
    "year": 1990
    }
}

Na segunda chamada com o mesmo CPF, a resposta vem do cache sem consultar a API novamente.


10. Boas práticas

  • Pipeline de middlewares — Decomponha a lógica em middlewares independentes: validação, cache, consulta e resposta. Isso facilita testes e reutilização.

  • Timeout — O middleware de lookup usa AbortController com 5 segundos para evitar conexões penduradas. A API da CPFHub.io responde em ~900ms, então 5s é uma margem confortável.

  • Cache — O middleware de cache evita consultas duplicadas e economiza requisições do plano.

  • Variáveis de ambiente — Use dotenv para gerenciar a chave de API. Nunca hardcode no código.

  • Rate limit local — Proteja seu endpoint de abusos com rate limiting no lado do servidor. A documentação do Express.js detalha como compor middlewares para esse fim.

  • Testes — Teste cada middleware isoladamente com mocks de req, res e next.


Perguntas frequentes

O que é um middleware customizado no Express.js e por que usá-lo para validação de CPF?

Um middleware no Express.js é uma função que intercepta a requisição antes de ela chegar ao handler final, podendo modificar o req, o res ou chamar next() para continuar o pipeline. Para validação de CPF, essa abordagem separa responsabilidades: um middleware valida o formato, outro consulta o cache, outro chama a API — tornando cada peça testável de forma independente.

Como o pipeline de middlewares afeta a performance da consulta de CPF?

A maior parte da latência vem da chamada externa à API, que responde em ~900ms. O middleware de cache é o ponto mais impactante: numa segunda consulta ao mesmo CPF dentro da janela de 1 hora, a resposta sai em menos de 1ms, sem trafegar pela rede. O middleware de validação de formato tem custo praticamente zero — ele só executa regex sobre uma string de 11 dígitos.

A API CPFHub.io bloqueia requisições quando o limite do plano é atingido?

Não. A API não bloqueia quando o limite mensal é atingido — o comportamento é cobrar R$0,15 por consulta excedente automaticamente. O plano gratuito oferece 50 consultas/mês e o Pro inclui 1.000 consultas por R$149/mês. Implementar cache e rate limiting local reduz o consumo desnecessário de cota.

Como proteger a chave de API ao fazer deploy do servidor Express.js?

Nunca inclua a chave de API no código-fonte nem no repositório git. Use variáveis de ambiente injetadas pela plataforma de deploy (Railway, Render, Heroku, etc.) e carregue-as com dotenv apenas em desenvolvimento local. Em produção, configure diretamente nas variáveis de ambiente do servidor — jamais num .env commitado.



Conclusão

O Express.js com middlewares customizados oferece uma integração modular e flexível com a API da CPFHub.io

Cadastre-se em cpfhub.io

CPFHub.io

Pronto para integrar a API?

50 consultas gratuitas para testar agora. Sem cartão de crédito. Acesso imediato à documentação.

Redação CPFHub.io

Sobre a redação

Redação CPFHub.io

Time editorial especializado em APIs de CPF, identidade digital e compliance no mercado brasileiro. Produzimos guias técnicos, análises regulatórias e tutoriais sobre LGPD e KYC para desenvolvedores e líderes de produto.

WhatsAppFale conosco via WhatsApp