Hookinator é um projeto desenvolvido em OCaml, utilizando a biblioteca Lwt para construir um servidor assíncrono robusto de webhooks. Seu objetivo é demonstrar como a programação funcional pode ser aplicada para tornar a comunicação via webhooks HTTP mais eficiente e robusta, promovendo boas práticas de desenvolvimento.
O projeto simula todo o ciclo de vida de um webhook: recepção via HTTP, validação rigorosa de payloads, persistência de transações em SQLite e envio de notificações baseadas em eventos. Boas práticas de arquitetura funcional, logging estruturado e modularização tornam o Hookinator um exemplo prático de como estruturar sistemas reativos com OCaml, facilitando manutenção e evolução do código.
- 🔄 Processamento de Webhooks: Recebe e processa webhooks HTTP de forma assíncrona
- 💾 Persistência de Dados: Armazena transações em banco de dados SQLite para auditoria
- 📧 Sistema de Notificações: Envia notificações personalizáveis baseadas nos eventos recebidos
- ✅ Validação Robusta: Valida dados de entrada com verificação de integridade e tipos de eventos
- 🔧 Configuração Automática: Carregamento automático de variáveis de ambiente via arquivo
.env - 🚀 Alta Performance: Construído com Lwt para programação assíncrona eficiente
- 📊 Logging Estruturado: Sistema de logs detalhado para monitoramento e debug
- 🧪 Testes Integrados: Suite completa de testes unitários com Alcotest
O sistema segue uma arquitetura modular baseada em componentes funcionais:
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
│ HTTP Client │───▶│ Hookinator │───▶│ Database │
│ (Webhook) │◀———│ Server │ │ (SQLite) │
└─────────────────┘ └──────────────────┘ └─────────────────┘
│
▼
┌──────────────┐
│ Notification │
│ System │
└──────────────┘
hookinator/
├── bin/ # Executável principal
│ ├── dune # Configuração do executável
│ └── main.ml # Ponto de entrada da aplicação
├── lib/ # Biblioteca principal
│ ├── config.ml # Configurações e carregamento do .env
│ ├── database.ml # Interface com banco de dados SQLite
│ ├── dune # Configuração da biblioteca
│ ├── handlers.ml # Manipuladores de requisições HTTP
│ ├── hookinator.ml # Módulo principal e API pública
│ ├── notification.ml # Sistema de notificações
│ ├── transaction.ml # Lógica de transações e modelos
│ ├── types.ml # Definições de tipos compartilhados
│ └── validation.ml # Validação de dados e schemas
├── test/ # Testes
│ ├── dune # Configuração de testes
│ └── test_hookinator.ml # Testes unitários
├── .env # Configurações de ambiente (criado pelo usuário)
├── dune-project # Configuração do projeto Dune
├── hookinator.opam # Metadados do pacote OPAM
├── webhook_transactions.db # Banco de dados SQLite
└── LICENSE # Licença MIT
bin/main.ml: Ponto de entrada que inicializa o servidor HTTPlib/hookinator.ml: API principal e orquestração dos componenteslib/config.ml: Gerenciamento de configuraçõeslib/handlers.ml: Manipuladores de rotas HTTP e processamento de webhookslib/database.ml: Camada de abstração para operações com SQLitelib/transaction.ml: Modelos de dados e lógica de transaçõeslib/notification.ml: Sistema de envio de notificaçõeslib/validation.ml: Validação robusta de payloads e eventoslib/types.ml: Tipos de dados compartilhados entre módulos
- OCaml >= 5.2.0
- Dune >= 3.0
- OPAM >= 2.1
As dependências são gerenciadas pelo arquivo hookinator.opam.
-
Clone o repositório:
git clone <repository-url> cd hookinator
-
Configure o ambiente OCaml:
# Se necessário, crie um switch local opam switch create . 5.2.0 # Instale as dependências opam install . --deps-only --with-test
-
Compile o projeto:
dune build
O Hookinator carrega automaticamente as configurações do arquivo .env. Crie um arquivo .env na raiz do projeto baseado no exemplo:
# Copie o arquivo de exemplo
cp .env.example .env
# Edite com suas configurações
nano .envPara iniciar o servidor, você pode definir as variáveis de ambiente diretamente ou usar um arquivo .env com o arquivo env_setup.sh:
source env_setup.sh# Executar diretamente
dune exec hookinator
# Em modo de desenvolvimento (com logs verbosos)
HOOKINATOR_LOG_LEVEL=debug dune exec hookinator
# Especificar porta customizada (sobrescreve .env)
HOOKINATOR_PORT=8080 dune exec hookinatorO servidor estará disponível em http://localhost:3000 (ou na porta especificada).
| Variável | Padrão | Descrição |
|---|---|---|
HOOKINATOR_PORT |
3000 |
Porta do servidor HTTP |
HOOKINATOR_DB_PATH |
webhook_transactions.db |
Caminho do banco SQLite |
HOOKINATOR_LOG_LEVEL |
info |
Nível de log (debug, info, warn, error) |
HOOKINATOR_TOKEN |
(obrigatório) | Token de autenticação para webhooks |
HOOKINATOR_EXPECTED_AMOUNT |
49.90 |
Valor esperado para validação |
HOOKINATOR_EXPECTED_CURRENCY |
BRL |
Moeda esperada para validação |
HOOKINATOR_CONFIRM_URL |
http://localhost:8000/confirmar |
URL de confirmação |
HOOKINATOR_CANCEL_URL |
http://localhost:8000/cancelar |
URL de cancelamento |
HOOKINATOR_MAX_PAYLOAD_SIZE |
1048576 |
Tamanho máximo do payload (bytes) |
HOOKINATOR_MIN_TRANSACTION_ID_LENGTH |
5 |
Tamanho mínimo do ID da transação |
{
"event": "payment_success",
"transaction_id": "abc123",
"amount": "49.90",
"currency": "BRL",
"timestamp": "2024-01-01T12:00:00Z"
}O sistema valida rigorosamente os tipos de eventos aceitos:
payment_success- Pagamento processado com sucessopayment_failed- Falha no processamento do pagamentopayment_pending- Pagamento pendente de confirmaçãosubscription_created- Nova assinatura criadasubscription_cancelled- Assinatura canceladarefund_processed- Reembolso processado
POST /webhook- Receber webhooks (requer token de autenticação)GET /health- Status do serviçoGET /metrics- Métricas básicas (opcional)
O projeto inclui uma suíte completa de testes que carrega automaticamente as configurações do .env:
# Executar todos os testes
dune test
# Executar com saída verbosa
dune test --verbose
# Executar testes específicos
dune exec test/test_hookinator.exeOs testes cobrem:
- Validação de payloads válidos e inválidos
- Verificação de tipos de eventos
- Autenticação de transações
- Validação de configurações
O projeto inclui um script Python para testar o endpoint de webhook:
# Certifique-se de que o servidor está rodando
dune exec hookinator &
# Execute o teste
python test_webhook.py
# Parar o servidor
kill %1# Testar endpoint de webhook com evento válido
curl -X POST http://localhost:3000/webhook \
-H "Content-Type: application/json" \
-H "Authorization: Bearer seu-token-secreto-aqui" \
-d '{
"event": "payment_success",
"transaction_id": "test123",
"amount": "49.90",
"currency": "BRL",
"timestamp": "2024-01-01T12:00:00Z"
}'
# Testar com evento inválido
curl -X POST http://localhost:3000/webhook \
-H "Content-Type: application/json" \
-H "Authorization: Bearer seu-token-secreto-aqui" \
-d '{
"event": "invalid_event",
"transaction_id": "test123",
"amount": "49.90",
"currency": "BRL",
"timestamp": "2024-01-01T12:00:00Z"
}'
# Verificar saúde do serviço
curl http://localhost:3000/healthO Hookinator utiliza logging estruturado com diferentes níveis de verbosidade. Os logs incluem:
- Requisições recebidas
- Transações processadas
- Validações de eventos
- Erros de validação
- Notificações enviadas
- Carregamento de configurações
O banco de dados SQLite (webhook_transactions.db) armazena:
- Histórico de todas as transações
- Timestamps de processamento
- Status de processamento
- Metadados dos webhooks
- Validação de token: Autenticação obrigatória via header Authorization
- Validação de eventos: Apenas eventos predefinidos são aceitos
- Limitação de payload: Tamanho máximo configurável
- Sanitização de dados: Validação rigorosa de tipos e formatos
- Logs de auditoria: Registro completo de todas as operações
- Configuração segura: Carregamento automático de variáveis sensíveis via
.env
Contribuições são bem-vindas! Para contribuir:
- Fork o projeto
- Crie uma branch para sua feature (
git checkout -b feature/AmazingFeature) - Commit suas mudanças (
git commit -m 'Add some AmazingFeature') - Push para a branch (
git push origin feature/AmazingFeature) - Abra um Pull Request
- Use
dune fmtpara formatação - Execute
dune testantes de commits - Siga as convenções de naming do OCaml
- Documente funções públicas
- Mantenha o arquivo
.env.exampleatualizado - Adicione testes para novas funcionalidades
Este projeto está licenciado sob a Licença MIT - veja o arquivo LICENSE para detalhes.
⭐ Se este projeto foi útil, considere dar uma estrela no GitHub!
O Hookinator foi idealizado como uma demonstração técnica para explorar, de forma aplicada, conceitos aprendidos em sala de aula sobre programação funcional, concorrência assíncrona e arquitetura de sistemas distribuídos.