@panudet_ingai/hookniew
v1.0.2
Published
HookNiew — Webhook reliability relay (Rust + Redis + Postgres). Queued -> Delivered -> Logged
Downloads
485
Maintainers
Readme
HookNiew — Webhook Reliability Service
เดิมชื่อ
webhook-reliabilitเปลี่ยนเป็น HookNiew (Queued → Delivered → Logged)
บริการรับ Webhook ที่เน้นความน่าเชื่อถือ สร้างด้วย Rust (Axum) พร้อม Rate Limiting ผ่าน Redis, API Key Authentication, และการเชื่อมต่อ PostgreSQL (Supabase)
โปรเจกต์นี้มี 2 ส่วนหลักที่ทำงานร่วมกัน:
- HTTP Server — รับ request webhook ผ่าน Axum (port
6254) - N-API Native Addon — expose ฟังก์ชัน Rust ให้ Node.js/TypeScript เรียกใช้ผ่าน
napi-rs
Tech Stack
| ส่วน | เทคโนologi | |------|-----------| | Web Framework | Axum 0.8 | | Runtime | Tokio | | Database | SQLx + PostgreSQL (Supabase) | | Cache / Rate Limit | Redis (Upstash) + redis-rate | | Node.js Binding | NAPI-RS | | TLS | rustls |
Request Flow
เมื่อ client ยิง request มาที่ /v1 หรือ /v1/health:
Client Request
│
▼
┌─────────────────────┐
│ Rate Limit │ ← ตรวจ IP (X-Forwarded-For) ผ่าน Redis
│ (ratelimit.rs) │ เกิน limit → 429 Too Many Requests
└─────────┬───────────┘
│
▼
┌─────────────────────┐
│ API Key Auth │ ← ตรวจ header `wh-rel-api-key`
│ (auth.rs) │ ไม่มี/ผิด → 401 Unauthorized
└─────────┬───────────┘
│
▼
┌─────────────────────┐
│ Handler │ ← เช่น health check → 200 OK
│ (handlers/) │
└─────────────────────┘Rate limit ปัจจุบัน: 1 request / 5 วินาที, burst สูงสุด 10 (กำหนดใน ratelimit.rs)
โครงสร้าง Project
hookniew/
├── src/ # Rust source code
│ ├── main.rs # Entry point ของ HTTP server
│ ├── lib.rs # Library root + N-API exports
│ │
│ ├── app/ # Application bootstrap
│ │ ├── mod.rs # build_state(), build_router(), run()
│ │ └── state.rs # AppState (db pool + rate limiter)
│ │
│ ├── config/ # การตั้งค่าเริ่มต้น
│ │ └── mod.rs # โหลด .env + ติดตั้ง rustls crypto provider
│ │
│ ├── infra/ # Infrastructure / External services
│ │ ├── postgres.rs # เชื่อมต่อ Supabase PostgreSQL
│ │ └── redis.rs # เชื่อมต่อ Redis + สร้าง rate limiter
│ │
│ ├── router/ # HTTP routing
│ │ ├── mod.rs
│ │ └── v1/
│ │ ├── app_routers.rs # กำหนด routes + middleware layers
│ │ └── middleware/
│ │ ├── auth.rs # ตรวจ API key
│ │ └── ratelimit.rs# จำกัดจำนวน request
│ │
│ ├── handlers/ # Request handlers (business endpoints)
│ │ ├── health.rs # GET /v1, /v1/health
│ │ └── api_key.rs # validate key endpoint (เตรียมไว้)
│ │
│ ├── core/ # Domain logic ที่ไม่ผูกกับ HTTP
│ │ ├── api_key.rs # validate API key
│ │ └── version.rs # ชื่อและเวอร์ชัน service
│ │
│ ├── sdk/ # N-API SDK สำหรับ Node.js/TypeScript
│ │ ├── mod.rs # export ฟังก์ชัน validate_api_key, get_service_info
│ │ ├── client.rs # WebhookReliabilityClient (HTTP client)
│ │ └── types.rs # Type definitions สำหรับ N-API
│ │
│ └── libraries/ # Utility helpers
│ └── env.rs # อ่าน environment variables
│
├── tests/ # Integration tests
│ ├── common/mod.rs # init_test_env() สำหรับทุก test
│ ├── connect_db.rs # ทดสอบ PostgreSQL connection
│ ├── redis.rs # ทดสอบ Redis connection
│ └── rate_limit.rs # ทดสอบ rate limiter + middleware
│
├── typescript/ # TypeScript examples
├── __test__/ # N-API addon tests (ava)
├── Cargo.toml # Rust dependencies
├── package.json # Node.js / N-API build scripts
└── .env # Environment variables (ไม่ commit)อธิบายแต่ละ Folder
src/app/ — Application Bootstrap
จุดเริ่มต้นของแอป HTTP
| ไฟล์ | หน้าที่ |
|------|--------|
| mod.rs | run() เริ่ม server, build_state() สร้าง DB pool + limiter, build_router() ประกอบ routes |
| state.rs | AppState — เก็บ shared state ที่ middleware และ handlers ใช้ร่วมกัน |
main.rs เรียกแค่ hookniew::app::run() — logic ทั้งหมดอยู่ใน lib
src/config/ — Configuration
| ไฟล์ | หน้าที่ |
|------|--------|
| mod.rs | init() — โหลด .env และติดตั้ง rustls CryptoProvider (จำเป็นสำหรับ Redis TLS) |
src/infra/ — Infrastructure Layer
เชื่อมต่อ external services โดยไม่มี business logic
| ไฟล์ | หน้าที่ |
|------|--------|
| postgres.rs | สร้าง SQLx connection pool ไป Supabase (port 5432 session pooler แนะนำ) |
| redis.rs | สร้าง Redis client และ redis_rate::Limiter สำหรับ rate limiting |
หมายเหตุ: ใช้
redis2 เวอร์ชัน —redis 1.6สำหรับงานทั่วไป,redis 0.29(aliasredis-v029) สำหรับredis-ratecrate
src/router/ — HTTP Routing
| ไฟล์ | หน้าที่ |
|------|--------|
| v1/app_routers.rs | กำหนด routes และเรียง middleware layers |
| v1/middleware/auth.rs | ตรวจ header wh-rel-api-key ก่อนเข้า handler |
| v1/middleware/ratelimit.rs | จำกัด request ตาม IP ผ่าน Redis token bucket |
Middleware order (จากนอก → ใน): Rate Limit → Auth → Handler
src/handlers/ — Request Handlers
รับ HTTP request หลังผ่าน middleware แล้ว ส่ง response กลับ
| ไฟล์ | Endpoint | หน้าที่ |
|------|----------|--------|
| health.rs | GET /v1, GET /v1/health | ตรวจสอบว่า service ยังทำงาน |
| api_key.rs | (เตรียมไว้) | validate API key แบบ standalone |
src/core/ — Domain Logic
Logic ที่ไม่ผูกกับ HTTP framework — ใช้ได้ทั้ง server และ N-API
| ไฟล์ | หน้าที่ |
|------|--------|
| api_key.rs | ตรวจว่า API key ถูกต้องหรือไม่ |
| version.rs | ชื่อและเวอร์ชัน service |
src/sdk/ — Node.js / TypeScript SDK
Expose Rust functions ให้ Node.js ผ่าน N-API
| ไฟล์ | หน้าที่ |
|------|--------|
| mod.rs | validate_api_key(), get_service_version(), get_service_info() |
| client.rs | WebhookReliabilityClient — HTTP client เรียก API จาก TypeScript |
| types.rs | Type definitions (HealthResponse, ValidateKeyResponse, etc.) |
tests/ — Integration Tests
ทดสอบกับ service จริง (ต้องมี .env ที่ตั้งค่าถูกต้อง)
| ไฟล์ | ทดสอบ |
|------|--------|
| connect_db.rs | เชื่อมต่อ Supabase + query ข้อมูล |
| redis.rs | PING Redis ทั้ง client ปกติและ rate-limit client |
| rate_limit.rs | Limiter โดยตรง + middleware คืน 429 + auth คืน 401 |
Environment Variables
สร้างไฟล์ .env ที่ root ของ project:
# Supabase PostgreSQL — ใช้ Session Pooler (port 5432) ไม่ใช่ Transaction (6543)
SUPABASE_URL_DATABASE=postgresql://postgres.[project-ref]:[password]@aws-0-[region].pooler.supabase.com:5432/postgres
# Upstash Redis — ใช้ rediss:// สำหรับ TLS
REDIS_URL=rediss://default:[token]@[host].upstash.io:6379| Variable | คำอธิบาย |
|----------|----------|
| SUPABASE_URL_DATABASE | PostgreSQL connection string จาก Supabase Dashboard |
| REDIS_URL | Redis connection string จาก Upstash Dashboard |
ถ้า password มีอักขระพิเศษ (เช่น
@) ต้อง URL-encode ก่อน (@→%40)
Getting Started
Prerequisites
รัน HTTP Server
# ติดตั้ง dependencies
cargo build
# รัน server (port 6254)
cargo runทดสอบ Health Check
curl http://localhost:6254/v1/health \
-H "wh-rel-api-key: PA-WEBHOOK-API-KEY"Response:
{
"status": "ok",
"name": "Webhook Reliability Service",
"version": "1.0.0"
}รัน Tests
# Rust integration tests (ต้องมี .env)
cargo test
# N-API addon tests
yarn install
yarn build
yarn testAPI Reference
Headers
| Header | Required | คำอธิบาย |
|--------|----------|----------|
| wh-rel-api-key | ✅ | API key สำหรับ authentication |
| X-Forwarded-For | ❌ | IP ของ client (ใช้สำหรับ rate limiting) |
Endpoints
| Method | Path | Auth | คำอธิบาย |
|--------|------|------|----------|
| GET | / | ❌ | Hello World (ไม่มี middleware) |
| GET | /v1 | ✅ | Health check |
| GET | /v1/health | ✅ | Health check |
Response Codes
| Code | ความหมาย |
|------|----------|
| 200 | สำเร็จ |
| 401 | ไม่มี API key หรือ key ไม่ถูกต้อง |
| 429 | เกิน rate limit |
| 500 | Redis error ระหว่าง rate limit check |
Build N-API Addon
yarn install
yarn build # release build
yarn build:debug # debug buildTypeScript client:
import { WebhookReliabilityClient } from 'hookniew'
const client = new WebhookReliabilityClient({
apiKey: 'PA-WEBHOOK-API-KEY',
baseUrl: 'http://localhost:6254',
})
const health = await client.health()
console.log(health)License
MIT — ดู LICENSE
