Para integrar validação de CPF em Clojure com Ring e Compojure, você usa a biblioteca clj-http para chamar GET https://api.cpfhub.io/cpf/{CPF} com o header x-api-key, deserializa o JSON com cheshire e retorna mapas imutáveis com chaves :ok ou :error para tratamento funcional de erros. A latência típica da API é de ~900ms — configure :socket-timeout e :connection-timeout acima desse valor para evitar falhas espúrias. A combinação de funções puras e desenvolvimento via REPL torna a integração e o diagnóstico de problemas especialmente ágeis no ecossistema Clojure.
1. Pré-requisitos
-
Clojure 1.11+ e Leiningen (ou deps.edn) instalados. Consulte o guia de início rápido do Clojure para instruções de instalação.
-
Uma conta gratuita na CPFHub.io
2. Configure o projeto
No project.clj, adicione as dependências:
;; project.clj
(defproject cpf-validator "0.1.0"
:description "Validação de CPF via API CPFHub.io"
:dependencies [[org.clojure/clojure "1.11.1"]
[ring/ring-core "1.10.0"]
[ring/ring-jetty-adapter "1.10.0"]
[ring/ring-json "0.5.1"]
[compojure "1.7.1"]
[clj-http "3.12.3"]
[cheshire "5.12.0"]
[environ "1.2.0"]]
:main cpf-validator.core
:plugins [[lein-environ "1.2.0"]])
3. Configure as variáveis de ambiente
Crie o arquivo profiles.clj para desenvolvimento:
;; profiles.clj (NÃO versione este arquivo)
{:dev {:env {:cpfhub-api-key "SUA_CHAVE_DE_API"
:cpfhub-base-url "https://api.cpfhub.io"
:cpfhub-timeout "5000"}}}
4. Crie o módulo de configuração
;; src/cpf_validator/config.clj
(ns cpf-validator.config
(:require [environ.core :refer [env]]))
(def cpfhub-config
{:api-key (env :cpfhub-api-key)
:base-url (env :cpfhub-base-url "https://api.cpfhub.io")
:timeout (Integer/parseInt (env :cpfhub-timeout "5000"))})
5. Implemente o serviço de consulta
Crie funções puras para a lógica de consulta:
;; src/cpf_validator/cpfhub.clj
(ns cpf-validator.cpfhub
(:require [clj-http.client :as http]
[cheshire.core :as json]
[clojure.string :as str]
[cpf-validator.config :refer [cpfhub-config]]))
(defn limpar-cpf
"Remove caracteres não numéricos do CPF."
[cpf]
(str/replace cpf #"\D" ""))
(defn cpf-valido?
"Verifica se o CPF tem 11 dígitos."
[cpf]
(= 11 (count (limpar-cpf cpf))))
(defn- mapear-erro
"Mapeia status HTTP para mensagem de erro."
[status]
(case status
400 {:error "CPF com formato inválido" :status 400}
401 {:error "Chave de API inválida ou ausente" :status 401}
404 {:error "CPF não encontrado na base de dados" :status 404}
{:error (str "Erro HTTP " status) :status status}))
(defn consultar-cpf
"Consulta dados de um CPF na API da CPFHub.io.
Retorna {:ok data} em caso de sucesso ou {:error msg :status code} em caso de erro."
[cpf]
(let [cpf-limpo (limpar-cpf cpf)]
(if-not (= 11 (count cpf-limpo))
{:error "CPF deve conter exatamente 11 dígitos" :status 400}
(try
(let [url (str (:base-url cpfhub-config) "/cpf/" cpf-limpo)
response (http/get url
{:headers {"x-api-key" (:api-key cpfhub-config)
"Accept" "application/json"}
:socket-timeout (:timeout cpfhub-config)
:connection-timeout (:timeout cpfhub-config)
:as :json
:throw-exceptions false})]
(if (= 200 (:status response))
(let [body (:body response)]
(if (:success body)
{:ok (:data body)}
{:error "Resposta inesperada da API" :status 500}))
(mapear-erro (:status response))))
(catch java.net.SocketTimeoutException _
{:error "Timeout ao consultar a API da CPFHub" :status 504})
(catch Exception e
{:error (str "Erro de conexão: " (.getMessage e)) :status 502})))))
6. Crie as rotas com Compojure
Configure as rotas da API:
;; src/cpf_validator/routes.clj
(ns cpf-validator.routes
(:require [compojure.core :refer [defroutes GET]]
[compojure.route :as route]
[ring.util.response :as response]
[cpf-validator.cpfhub :as cpfhub]))
(defn- consulta-cpf-handler
"Handler para consulta de CPF."
[cpf]
(let [resultado (cpfhub/consultar-cpf cpf)]
(if (:ok resultado)
(response/response {:success true :data (:ok resultado)})
(-> (response/response {:success false :error (:error resultado)})
(response/status (:status resultado 500))))))
(defroutes app-routes
(GET "/api/cpf/:cpf" [cpf] (consulta-cpf-handler cpf))
(route/not-found {:success false :error "Recurso não encontrado"}))
7. Configure o middleware e inicie o servidor
;; src/cpf_validator/core.clj
(ns cpf-validator.core
(:require [ring.adapter.jetty :refer [run-jetty]]
[ring.middleware.json :refer [wrap-json-response wrap-json-body]]
[ring.middleware.params :refer [wrap-params]]
[cpf-validator.routes :refer [app-routes]])
(:gen-class))
(def app
(-> app-routes
wrap-json-response
(wrap-json-body {:keywords? true})
wrap-params))
(defn -main
"Inicia o servidor HTTP."
[& args]
(let [port (Integer/parseInt (or (System/getenv "PORT") "3000"))]
(println (str "Servidor iniciado na porta " port))
(run-jetty app {:port port :join? false})))
8. Teste a integração
Inicie o servidor e faça uma requisição de teste:
lein run
curl -X GET http://localhost:3000/api/cpf/12345678900
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
}
}
9. Teste no REPL
Uma das vantagens do Clojure é o desenvolvimento interativo via REPL:
;; No REPL
(require '[cpf-validator.cpfhub :as cpfhub])
;; Testar consulta
(cpfhub/consultar-cpf "12345678900")
;; => {:ok {:cpf "12345678900" :name "João da Silva" ...}}
;; Testar CPF inválido
(cpfhub/consultar-cpf "123")
;; => {:error "CPF deve conter exatamente 11 dígitos" :status 400}
;; Verificar validação
(cpfhub/cpf-valido? "123.456.789-00")
;; => true
10. Boas práticas
-
Imutabilidade -- Todas as funções retornam mapas imutáveis. Erros são representados como dados, não exceções.
-
clj-http -- Use
:throw-exceptions falsepara tratar erros HTTP como dados em vez de exceções. -
Timeout -- Configure
:socket-timeoute:connection-timeoutnoclj-httppara evitar requisições travadas. A latência da API CPFHub.io é de ~900ms; use 5000ms como ponto de partida. -
environ -- Use a biblioteca
environpara gerenciar configurações de forma segura via variáveis de ambiente. -
REPL -- Aproveite o REPL para testar integrações interativamente durante o desenvolvimento.
-
LGPD -- A API da CPFHub.io é 100% compatível com a LGPD. Garanta que dados pessoais sejam tratados conforme a legislação em sua aplicação Clojure.
Perguntas frequentes
Por que usar mapas com :ok e :error em vez de exceções no Clojure?
Clojure favorece dados sobre exceções: um mapa {:error "mensagem" :status 400} pode ser inspecionado, logado, transformado e passado entre funções sem nenhuma cerimônia. Exceções quebram o fluxo funcional e são mais difíceis de testar no REPL. A biblioteca clj-http com :throw-exceptions false reforça esse padrão ao entregar respostas de erro como dados normais — o handler decide o que fazer com elas, mantendo as funções de consulta puras e testáveis.
Como o clj-http lida com a latência de ~900ms da API CPFHub.io?
O clj-http usa conexões bloqueantes por padrão. Com :socket-timeout 5000 e :connection-timeout 5000, a biblioteca aguarda até 5 segundos pela resposta antes de lançar java.net.SocketTimeoutException, que o catch na função consultar-cpf converte em {:error "Timeout..." :status 504}. Para cargas maiores, considere usar clj-http.client com um pool de conexões ou migrar para hato, que usa o HttpClient assíncrono do Java 11.
O que acontece quando o limite de consultas do plano gratuito é atingido?
A API CPFHub.io não bloqueia nem retorna erro ao ultrapassar o limite. O plano gratuito inclui 50 consultas por mês e, ao esgotá-las, cada consulta adicional é cobrada a R$0,15 automaticamente. O código Clojure não precisa tratar nenhum caso especial para isso — a resposta continua sendo um 200 OK com os dados do CPF. Para controle de custos, monitore o uso pelo painel em app.cpfhub.io.
Como testar a função consultar-cpf sem fazer chamadas reais à API?
No REPL ou em testes com clojure.test, use with-redefs para substituir clj-http.client/get por uma função que retorna um mapa fixo. Exemplo: (with-redefs [http/get (fn [_ _] {:status 200 :body {:success true :data {...}}})] (consultar-cpf "12345678900")). Essa abordagem não requer mocks de objetos nem frameworks externos — é só Clojure puro, compatível com o ciclo de desenvolvimento via REPL.
Conclusão
Integrar 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.
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.



