Skip to content

Repository files navigation

Hooklyn

Public Webhook Testing & Request Inspection Service

Dart License Render Creator

Hooklyn is a production-ready, zero-authentication webhook testing tool. Create temporary HTTP endpoints, capture every incoming request, and inspect method, headers, query parameters, cookies, body (JSON, form-data, text, XML, raw), client IP, timestamps, and size — all in a polished real-time web UI.

Created by Blitz · GitHub/social: blitzlabx


Features

  • Temporary webhook endpoints — one-click generation of unique 8-character IDs
  • Full request capture — GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS and any other method
  • Rich inspection — headers, query string, cookies, body, content-type, client IP (proxy-aware), user-agent, size, timestamps
  • Body support — JSON (with parsed view), application/x-www-form-urlencoded, plain text, XML, and binary (base64)
  • Real-time updates — Server-Sent Events (SSE) push new requests to the browser instantly
  • Request history — per-bin history with configurable max size (default 100)
  • Copy webhook URL and copy as curl
  • Request replay — resend a captured request to any target HTTP/HTTPS URL
  • Automatic expiration — inactive bins expire after configurable TTL (default 24 hours)
  • Rate limiting, request size limits, CORS, structured JSON API responses
  • Health endpoints — GET /ping and GET /health for UptimeRobot and load balancers
  • Dockerized and ready for Render deployment
  • No authentication — public by design for testing

Architecture

┌─────────────┐     HTTP/SSE      ┌──────────────────────────────┐
│  Browser UI │ ◄───────────────► │  Shelf server (Dart)         │
└─────────────┘                   │  ├── Static (public/)        │
                                  │  ├── /api/*  (REST + SSE)    │
┌─────────────┐     any method    │  ├── /{binId}  (capture)     │
│  curl / app │ ───────────────► │  ├── /ping, /health          │
└─────────────┘                   │  └── BinStore (in-memory)    │
                                  └──────────────────────────────┘
  • Runtime: Dart 3.13+, Shelf + shelf_router + shelf_static
  • Storage: In-memory BinStore with periodic cleanup (no external DB required)
  • Frontend: Vanilla JS + modern CSS (IBM Plex), no framework lock-in
  • Real-time: SSE per bin (/api/bins/:id/stream)

Quick start (local)

Prerequisites

Install & run

git clone https://github.com/blitzlabx/hooklyn.git
cd hooklyn
dart pub get
dart run bin/server.dart

Server listens on http://0.0.0.0:8080 (or $PORT).

Open the UI, click Create Webhook Endpoint, then send requests:

curl -X POST http://localhost:8080/<bin-id> \
  -H 'Content-Type: application/json' \
  -d '{"event":"payment.succeeded","amount":1999}'

API documentation

All API responses are JSON with the shape:

{
  "success": true,
  "data": { ... }
}

Errors:

{
  "success": false,
  "error": { "message": "..." }
}

Create bin

POST /api/bins
Content-Type: application/json

{
  "ttlHours": 24,
  "maxRequests": 100
}

Optional body. ttlHours clamped 1–168, maxRequests 10–500.

Response 201:

{
  "success": true,
  "data": {
    "id": "a1b2c3d4",
    "webhookUrl": "https://host/a1b2c3d4",
    "inspectUrl": "https://host/inspect/a1b2c3d4",
    "createdAt": "...",
    "expiresAt": "...",
    ...
  }
}

Get bin + requests

GET /api/bins/:id?limit=50

List requests

GET /api/bins/:id/requests?limit=100

Get single request

GET /api/bins/:id/requests/:requestId

Delete bin

DELETE /api/bins/:id

Real-time stream (SSE)

GET /api/bins/:id/stream

Events: request with JSON payload of the captured request. Heartbeats every ~25s.

Replay

POST /api/bins/:id/requests/:requestId/replay
Content-Type: application/json

{ "targetUrl": "https://example.com/webhook" }

Curl helper

GET /api/bins/:id/requests/:requestId/curl

Stats

GET /api/stats

Health

GET /ping     → text/plain "pong"
GET /health   → JSON status + store stats

Webhook usage examples

curl

# JSON
curl -X POST https://your-host/<bin-id> \
  -H 'Content-Type: application/json' \
  -d '{"hello":"hooklyn"}'

# Form
curl -X POST https://your-host/<bin-id> \
  -d 'name=Blitz&project=Hooklyn'

# Custom headers + path
curl -X PUT https://your-host/<bin-id>/orders/42 \
  -H 'X-Signature: abc' \
  -H 'Content-Type: application/xml' \
  -d '<order id="42"/>'

Dart

import 'package:http/http.dart' as http;

final res = await http.post(
  Uri.parse('https://your-host/<bin-id>'),
  headers: {'Content-Type': 'application/json'},
  body: '{"from":"dart"}',
);
print(res.body);

Docker

docker build -t hooklyn .
docker run --rm -p 8080:8080 \
  -e PORT=8080 \
  -e PUBLIC_BASE_URL=http://localhost:8080 \
  hooklyn

The image uses multi-stage build (AOT compile) and ships the public/ static assets.


Deploy on Render

  1. Push this repository to GitHub (blitzlabx/hooklyn or your fork).
  2. In Render: New → Web Service → Connect repo.
  3. Runtime: Docker (or use the included render.yaml).
  4. Set environment variables as needed (see below).
  5. Health check path: /health.
  6. After deploy, optionally set PUBLIC_BASE_URL to https://<your-service>.onrender.com so generated webhook URLs are absolute and correct behind the proxy.

render.yaml is provided for Blueprint-style deploys.


Environment variables

Variable Default Description
PORT 8080 Listen port (Render injects this)
PUBLIC_BASE_URL (inferred) Canonical public origin for webhook URLs
BIN_TTL_HOURS 24 Inactivity TTL for bins
MAX_REQUESTS_PER_BIN 100 Max stored requests per bin
MAX_BINS 10000 Soft cap on concurrent bins
MAX_BODY_BYTES 1048576 Max request body size (1 MiB)
RATE_LIMIT_MAX 120 Requests per window per IP
RATE_LIMIT_WINDOW_SEC 60 Rate-limit window in seconds

Health monitoring

  • UptimeRobot / similar: probe GET /ping (returns plain pong) or GET /health.
  • Both endpoints are lightweight and do not hit rate limits heavily; keep /ping for pure liveness.

Rate limits & security considerations

  • Per-IP sliding-window rate limiting (default 120 req/min).
  • Request body size capped (default 1 MiB).
  • CORS enabled for browser use (*).
  • No authentication by design — do not put secrets in webhook payloads you send to a public instance.
  • In-memory storage: data is lost on restart; bins expire automatically.
  • Replay feature sends the captured request to a user-supplied URL — use only with trusted targets.
  • Suitable for development and integration testing, not for production webhook reception of sensitive data without additional controls.

Limitations

  • Storage is in-memory only (no Redis/Postgres). Horizontal scaling will not share bins across instances.
  • Free Render instances spin down when idle; cold start may take a few seconds.
  • Binary bodies are stored base64-encoded and count toward size limits.
  • Maximum concurrent bins and requests per bin are configurable but finite to protect memory.

Development

dart pub get
dart run bin/server.dart          # run
dart test                         # tests
dart analyze                      # static analysis
dart format .                     # format

Formatting and recommended lints are configured via analysis_options.yaml (package:lints/recommended.yaml).


Project layout

bin/server.dart           # entrypoint
lib/
  handlers/               # API, webhook, health
  middleware/             # CORS, rate limit, size limit
  models/                 # Bin, CapturedRequest
  services/               # BinStore, RateLimiter
  utils/
public/                   # UI (index.html, styles.css, app.js)
test/
Dockerfile
render.yaml

Contributing

Issues and pull requests are welcome at github.com/blitzlabx/hooklyn.

  1. Fork and create a feature branch.
  2. Keep changes focused; add tests where practical.
  3. Run dart analyze and dart test before opening a PR.

Credits

Hooklyn is created and maintained by Blitz (blitzlabx).

All project credit goes to Blitz.


License

MIT License — free to use, modify, and distribute.

About

Public webhook testing & request inspection service. Create temporary endpoints, capture every request in real-time, inspect headers/body, and replay requests.i

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages