Como integrar validação de CPF em Cloudflare Workers com fetch API

Aprenda a criar um Cloudflare Worker que válida CPF usando a API CPFHub.io com fetch nativo, KV para cache e deploy global em edge.

Redação CPFHub.io
Redação CPFHub.io
··7 min de leitura
Como integrar validação de CPF em Cloudflare Workers com fetch API

Para integrar validação de CPF em Cloudflare Workers, crie um Worker em TypeScript que recebe o CPF via rota /cpf/{numero}, verifica o cache no KV e, se necessário, consulta a API da CPFHub.io com fetch nativo e o header x-api-key. Os Workers rodam na edge da rede Cloudflare — em mais de 300 datacenters — com cold starts abaixo de 5ms, tornando-os ideais para validações que precisam de resposta rápida próxima ao usuário. A documentação do Cloudflare Workers detalha o modelo de execução, limites de CPU e como configurar segredos com o Wrangler.


Configuração do projeto

Crie o projeto com o Wrangler, a CLI do Cloudflare:

npm create cloudflare@latest cpf-validator -- --type=hello-world
cd cpf-validator

Configure o wrangler.toml:

name = "cpf-validator"
main = "src/index.ts"
compatibility_date = "2024-01-01"

[vars]
ENVIRONMENT = "production"

[[kv_namespaces]]
binding = "CPF_CACHE"
id = "seu_kv_namespace_id"

Implementação do Worker

O Worker principal recebe requisições, consulta o cache e, se necessário, chama a API da CPFHub.io:

// src/index.ts

interface Env {
    CPFHUB_API_KEY: string;
    CPF_CACHE: KVNamespace;
    ENVIRONMENT: string;
}

interface CPFApiResponse {
    success: boolean;
    data?: {
    cpf: string;
    name: string;
    nameUpper: string;
    gender: string;
    birthDate: string;
    day: number;
    month: number;
    year: number;
    };
}

const CORS_HEADERS = {
    "Access-Control-Allow-Origin": "*",
    "Access-Control-Allow-Methods": "GET, OPTIONS",
    "Access-Control-Allow-Headers": "Content-Type",
};

const CACHE_TTL_SECONDS = 86400; // 24 horas
const API_TIMEOUT_MS = 10000;

function jsonResponse(body: object, status = 200): Response {
    return new Response(JSON.stringify(body), {
    status,
    headers: {
    ...CORS_HEADERS,
    "Content-Type": "application/json",
    "Cache-Control": "no-store",
    },
    });
}

function limparCPF(cpf: string): string {
    return cpf.replace(/\D/g, "");
}

function validarFormatoCPF(cpf: string): string | null {
    if (cpf.length !== 11) return "CPF deve conter 11 digitos";
    if (/^(\d)\1+$/.test(cpf)) return "CPF invalido";
    return null;
}

async function consultarCPFHub(
    cpf: string,
    apiKey: string
): Promise<CPFApiResponse> {
    const controller = new AbortController();
    const timeoutId = setTimeout(() => controller.abort(), API_TIMEOUT_MS);

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

    clearTimeout(timeoutId);

    if (!response.ok) {
    throw new Error(`API retornou status ${response.status}`);
    }

    return await response.json();
    } catch (error) {
    clearTimeout(timeoutId);
    throw error;
    }
}

export default {
    async fetch(request: Request, env: Env): Promise<Response> {
    // CORS preflight
    if (request.method === "OPTIONS") {
    return new Response(null, { headers: CORS_HEADERS });
    }

    if (request.method !== "GET") {
    return jsonResponse({ erro: "Metodo nao permitido" }, 405);
    }

    const url = new URL(request.url);
    const pathParts = url.pathname.split("/").filter(Boolean);

    // Rota: /cpf/:numero
    if (pathParts[0] !== "cpf" || !pathParts[1]) {
    return jsonResponse(
    { erro: "Use /cpf/{numero} para consultar" },
    400
    );
    }

    const cpf = limparCPF(pathParts[1]);
    const erroFormato = validarFormatoCPF(cpf);

    if (erroFormato) {
    return jsonResponse({ erro: erroFormato }, 400);
    }

    // Verificar cache KV
    const cacheKey = `cpf:${cpf}`;
    const cached = await env.CPF_CACHE.get(cacheKey, "json");

    if (cached) {
    return jsonResponse({
    valido: true,
    dados: cached,
    fonte: "cache",
    });
    }

    // Consultar API CPFHub.io
    try {
    const resultado = await consultarCPFHub(cpf, env.CPFHUB_API_KEY);

    if (!resultado.success || !resultado.data) {
    return jsonResponse({ erro: "CPF nao encontrado" }, 404);
    }

    const dados = {
    nome: resultado.data.name,
    cpf: resultado.data.cpf,
    genero: resultado.data.gender,
    dataNascimento: resultado.data.birthDate,
    };

    // Salvar no cache KV
    await env.CPF_CACHE.put(cacheKey, JSON.stringify(dados), {
    expirationTtl: CACHE_TTL_SECONDS,
    });

    return jsonResponse({
    valido: true,
    dados,
    fonte: "api",
    });
    } catch (error) {
    const mensagem =
    error instanceof DOMException && error.name === "AbortError"
    ? "Timeout na consulta de CPF"
    : `Erro: ${(error as Error).message}`;

    return jsonResponse({ erro: mensagem }, 500);
    }
    },
};

Cache distribuido com KV

O Cloudflare KV e um armazenamento key-value distribuido globalmente, ideal para cachear resultados de consultas de CPF. Crie o namespace:

# Criar KV namespace
npx wrangler kv:namespace create CPF_CACHE

# O comando retorna o ID -- adicione ao wrangler.toml

Vantagens do KV para cache de CPF:

  • Distribuição global -- O cache e replicado automaticamente em todos os datacenters.
  • TTL nativo -- A expiracao e gerenciada pelo Cloudflare, sem necessidade de limpeza manual.
  • Consistência eventual -- Atualizações propagam em até 60 segundos, aceitavel para dados de CPF.
  • Custo baixo -- O plano gratuito inclui 100.000 leituras e 1.000 escritas por dia.

Configuração de segredos

Armazene a chave de API como segredo do Worker:

# Definir segredo
npx wrangler secret put CPFHUB_API_KEY
# O CLI solicita o valor de forma segura

# Para desenvolvimento local, crie .dev.vars
echo "CPFHUB_API_KEY=sua_chave_aqui" > .dev.vars

Os segredos são criptografados e acessiveis apenas pelo Worker em tempo de execução, através do objeto env.


Deploy e testes

Deploy do Worker:

# Desenvolvimento local
npx wrangler dev

# Deploy para producao
npx wrangler deploy

Teste local:

curl http://localhost:8787/cpf/12345678901

Apos o deploy, o Worker estara disponível em https://cpf-validator.seu-subdominio.workers.dev/cpf/12345678901.


Rate limiting com Cloudflare

O Cloudflare oferece rate limiting nativo que pode ser configurado no dashboard ou via API:

// Implementacao de rate limiting no proprio Worker
async function verificarRateLimit(
    request: Request,
    env: Env
): Promise<boolean> {
    const ip = request.headers.get("CF-Connecting-IP") ?? "unknown";
    const rateLimitKey = `ratelimit:${ip}`;
    const contagem = parseInt(
    (await env.CPF_CACHE.get(rateLimitKey)) ?? "0"
    );

    if (contagem >= 10) {
    return false; // Limite excedido
    }

    await env.CPF_CACHE.put(rateLimitKey, String(contagem + 1), {
    expirationTtl: 60, // Reset a cada 60 segundos
    });

    return true;
}

Performance na edge

A principal vantagem dos Cloudflare Workers para validação de CPF e a latência:

MetricaWorkersLambda (sa-east-1)Cloud Functions
Cold start< 5ms200-800ms200-1000ms
Latência (Brasil)~10ms + API~20ms + API~15ms + API
Latência (Global)~10ms + APIVariavelVariavel

Como a API da CPFHub.io


Perguntas frequentes

O que é necessário para integrar validação de CPF em Cloudflare Workers?

A integração exige um projeto criado com o Wrangler, um KV namespace para cache e a chave de API da CPFHub.io armazenada como segredo (wrangler secret put). O Worker usa o fetch nativo do runtime para chamar GET https://api.cpfhub.io/cpf/{CPF} com o header x-api-key, sem necessidade de bibliotecas HTTP externas.

Qual é a latência total ao usar CPFHub.io em um Cloudflare Worker?

O Worker em si responde em poucos milissegundos (cold start praticamente irrelevante). A latência total depende da chamada à API CPFHub.io e do caminho de rede até o edge. Não publicamos um número fixo de latência — meça no seu ambiente (p95/p99) e use o timeout do AbortController com margem. Quando o resultado está no KV, a resposta fica bem mais rápida. Disponibilidade (SLA) por plano: Preços — Free 95%, Pro 99%, Corporate 99,9%.

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

Não. A API não bloqueia nem retorna 429 ao ultrapassar o limite do plano — ela continua respondendo e cobra R$0,15 por consulta adicional. O plano gratuito inclui 50 consultas/mês e o plano Pro oferece 1.000 consultas por R$149/mês. O cache KV com TTL de 24 horas ajuda a reduzir o consumo de cotas para CPFs consultados com frequência.

Como proteger a chave de API da CPFHub.io em um Cloudflare Worker?

Use o comando npx wrangler secret put CPFHUB_API_KEY para armazenar a chave de forma criptografada. Ela fica acessível apenas em tempo de execução via env.CPFHUB_API_KEY, sem aparecer no código-fonte, nos logs do dashboard ou nas variáveis de ambiente em texto plano. Nunca inclua a chave diretamente no wrangler.toml ou no código versionado.


Conclusão

Cloudflare Workers oferecem a menor latência possível para APIs de validação de CPF, com cold starts praticamente inexistentes e distribuição global automática. O KV fornece cache distribuido sem configuração, e os segredos manteem a chave de API protegida. Combinado 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