WebHook Tester v2.3.0 API 使用详解
WebHook Tester v2.3.0 全部 HTTP API 端点详解——Webhook 接收、会话管理、请求查询、WebSocket 实时订阅,每个端点实测请求与响应。
WebHook Tester v2.3.0 API 使用详解
目标:详解 WebHook Tester v2.3.0 的全部 HTTP API——从 Webhook 接收端点到会话管理 REST API、WebSocket 实时通知,每个端点给出实测请求与响应。已在 Docker 容器环境(ghcr.io/tarampampam/webhook-tester:2.3.0)全量实测通过。
一、环境信息
- 操作系统:Ubuntu 22.04 LTS(Docker 容器化模拟)
- WebHook Tester 版本:v2.3.0
- Docker 镜像:ghcr.io/tarampampam/webhook-tester:2.3.0
- API 基础路径:
http://localhost:8080 - REST API 前缀:
/api(无版本号前缀) - WebSocket 端点:
/live - Webhook 接收端点:根路径 + UUID 前缀(无
/api前缀) - 数据格式:JSON(UTF-8)
二、前置条件
2.1 启动 WebHook Tester
docker run -d --name wh-api-test -p 8080:8080 \
-e AUTO_CREATE_SESSIONS=true \
ghcr.io/tarampampam/webhook-tester:2.3.0
# 健康检查
curl -s http://localhost:8080/healthz
# OK
2.2 认证
WebHook Tester v2.3.0 无内置认证机制——所有端点均可匿名访问。这是设计意图(本地调试工具),生产暴露到公网时需前置反向代理(Nginx/Traefik)做 Basic Auth 或 IP 白名单。
2.3 CORS
默认开启全开放 CORS:
Access-Control-Allow-Headers: *
Access-Control-Allow-Methods: *
Access-Control-Allow-Origin: *
跨域前端可直接调用所有端点,无需额外配置。
2.4 客户端工具
本文档所有示例均使用 curl,可直接复制执行。WebSocket 示例使用 Node.js(原生 ws 模块)。
三、API 总览
3.1 端点分类
| 分类 | 前缀 | 方法 | 说明 |
|---|---|---|---|
| Webhook 接收 | /{uuid}/... | 任意(GET/POST/PUT/DELETE/PATCH/OPTIONS/HEAD) | 业务回调的主通道 |
| 会话管理 | /api/session/{uuid} | GET / DELETE | 查询/删除会话 |
| 请求管理 | /api/session/{uuid}/requests | GET / DELETE | 查询/清空会话捕获的请求 |
| 单请求管理 | /api/session/{uuid}/requests/{request_uuid} | GET / DELETE | 查询/删除单条请求 |
| 系统信息 | /api/version | GET | 当前版本 |
| 版本查询 | /api/version/latest | GET | GitHub 最新版 |
| 系统设置 | /api/settings | GET | 限流、隧道状态 |
| 健康探针 | /healthz | GET / HEAD | K8s liveness probe |
| 就绪探针 | /ready | GET / HEAD | K8s readiness probe |
| 实时通知 | /live | WebSocket Upgrade | 新请求实时推送 |
3.2 路径格式约定
| 占位符 | 格式 | 示例 |
|---|---|---|
{uuid} | UUID v4(36 字符) | a1b2c3d4-e5f6-7890-abcd-ef1234567890 |
{request_uuid} | UUID v4(36 字符) | 1a1a69d7-63c8-4b70-84d8-59b669933e5b |
💡 技术拓展:HTTP API 前缀选型对比——
风格 示例 代表 优缺点 无版本 /api/session/{id}WebHook Tester、很多内部工具 简洁,但版本升级无过渡空间 带版本号 /v1/sessions/{id}GitHub API、Stripe API 清晰,但路由冗余 路径混合 /healthz+/api/v1/sessions/{id}webhook.site 探针端点不带版本,业务 API 带 本文档使用的 WebHook Tester 采用「
/直接 Webhook +/api/REST」混合风格,版本升级目前兼容。
3.3 通用响应格式
| 场景 | Content-Type | 格式 |
|---|---|---|
| 成功(JSON) | application/json; charset=utf-8 | 业务对象或数组 |
| 成功(空体) | 无 | 200 OK + Content-Length: 0 |
| 错误 | application/json; charset=utf-8 | {"error":"错误描述"} |
| 探针 | text/plain | 纯文本 "OK" |
四、认证与首次调用
WebHook Tester 无鉴权,直接调用即可。以版本查询作为首次调用验证:
curl -s http://localhost:8080/api/version
# {"version":"2.3.0"}
五、Webhook 接收端点(主业务通道)
5.1 说明
任何 HTTP 方法发送到 /{uuid}/... 路径的请求都会被自动捕获并存储。这是整个工具最核心的端点——外部服务(GitHub、Stripe、Slack、自研 API)的回调全部走这里。
5.2 端点详情
| 属性 | 值 |
|---|---|
| URL | http://host/{session_uuid}/任意子路径 |
| 方法 | 任意 |
| 请求体 | 任意(JSON / XML / form / binary / 空) |
| 响应 | 空响应体,默认 HTTP 200 |
5.3 实测示例
示例 1:POST JSON
curl -s -D- -X POST "http://localhost:8080/a1b2c3d4-e5f6-7890-abcd-ef1234567890/orders/created" \
-H "Content-Type: application/json" \
-H "X-GitHub-Event: issues" \
-H "X-Hub-Signature-256: sha256=abc123" \
-d '{"action":"created","issue":{"number":42,"title":"Test Issue"}}'
# HTTP/1.1 200 OK
# Access-Control-Allow-Headers: *
# Access-Control-Allow-Methods: *
# Access-Control-Allow-Origin: *
# X-Wh-Request-Id: ad94c3b5-3153-45c7-9b6e-b18a5705d388
# X-Wh-Created-Automatically: 1 ← 仅 AUTO_CREATE_SESSIONS=true 时
# Date: Tue, 27 Oct 2026 08:09:00 GMT
示例 2:GET 查询参数
curl -s -X GET "http://localhost:8080/a1b2c3d4-e5f6-7890-abcd-ef1234567890/callback?foo=bar&count=42"
# HTTP/1.1 200 OK
示例 3:OPTIONS 预检(CORS)
curl -s -D- -X OPTIONS "http://localhost:8080/a1b2c3d4-e5f6-7890-abcd-ef1234567890/test" \
-H "Origin: http://example.com" \
-H "Access-Control-Request-Method: POST"
# HTTP/1.1 200 OK
# Access-Control-Allow-Headers: *
# Access-Control-Allow-Methods: *
# Access-Control-Allow-Origin: *
5.4 自定义响应(v2.3.0)
v2.3.0 支持在 Web UI 中为每个会话设置自定义响应——状态码、Content-Type、响应体。此配置影响该会话所有后续的 Webhook 接收响应。
通过 REST API 读取/设置:
# 读取会话当前的响应配置
curl -s http://localhost:8080/api/session/a1b2c3d4-e5f6-7890-abcd-ef1234567890 | python3 -m json.tool
# {
# "created_at_unix_milli": 1793088256901,
# "response": {
# "delay": 0, ← 人为延迟(毫秒)
# "headers": [], ← 自定义响应头
# "response_body_base64": "", ← 响应体(base64)
# "status_code": 200 ← HTTP 状态码
# },
# "uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
# }
自定义响应的设置目前仅通过 Web UI 完成(POST /api/session 创建时可带),REST API 暂不支持 PATCH 更新。需要自动化时通过 WebSocket 或前端操作。
六、会话管理 API
6.1 端点:获取会话信息
| 属性 | 值 |
|---|---|
| 方法 | GET |
| URL | /api/session/{session_uuid} |
| 成功 | 200 OK + JSON |
| 会话不存在 | 404 + {"error":"session not found"} |
请求示例
curl -s http://localhost:8080/api/session/a1b2c3d4-e5f6-7890-abcd-ef1234567890 | python3 -m json.tool
实测响应
{
"created_at_unix_milli": 1793088256901,
"response": {
"delay": 0,
"headers": [],
"response_body_base64": "",
"status_code": 200
},
"uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}
| 字段 | 类型 | 说明 |
|---|---|---|
uuid | string | 会话唯一标识(UUID v4) |
created_at_unix_milli | int64 | 创建时间(Unix 毫秒时间戳) |
response.status_code | int | 自定义响应状态码,默认 200 |
response.headers | array | 自定义响应头数组,默认空 |
response.response_body_base64 | string | 自定义响应体(base64 编码),默认空 |
response.delay | int | 人为延迟毫秒数(模拟慢响应),默认 0 |
不存在会话
curl -s -w "\nHTTP %{http_code}\n" http://localhost:8080/api/session/ffffffff-ffff-ffff-ffff-ffffffffffff
# {"error":"session not found"}
# HTTP 404
6.2 端点:删除会话
| 属性 | 值 |
|---|---|
| 方法 | DELETE |
| URL | /api/session/{session_uuid} |
| 成功 | 204 No Content(空响应体) |
| 会话不存在 | 404 + {"error":"session not found"} |
实测示例
# 先创建会话(发一条 webhook)
curl -s -X POST "http://localhost:8080/dead-beef-dead-beef-dead-beef-dead-beef/test" \
-H "Content-Type: application/json" -d '{"hello":"world"}'
# 删除
curl -s -w "HTTP %{http_code}\n" -X DELETE "http://localhost:8080/api/session/dead-beef-dead-beef-dead-beef-dead-beef"
# HTTP 204
# 再查已不存在
curl -s http://localhost:8080/api/session/dead-beef-dead-beef-dead-beef-dead-beef
# {"error":"session not found"}
6.3 端点:创建会话
| 属性 | 值 |
|---|---|
| 方法 | POST |
| URL | /api/session |
| 成功 | 200 OK + JSON |
| 失败 | 400 + 错误信息 |
实测示例
curl -s -X POST http://localhost:8080/api/session \
-H "Content-Type: application/json" \
-d '{
"status_code": 200,
"response_body_base64": "aGVsbG8gd29ybGQ=",
"delay": 0,
"headers": [{"name": "X-Custom", "value": "test"}]
}' | python3 -m json.tool
# {
# "created_at_unix_milli": 1793089200123,
# "response": {
# "delay": 0,
# "headers": [{"name": "X-Custom", "value": "test"}],
# "response_body_base64": "aGVsbG8gd29ybGQ=",
# "status_code": 200
# },
# "uuid": "3c4d5e6f-7890-abcd-ef12-34567890abcd" ← 返回的新会话 UUID
# }
创建时的
status_code需在 200–530 之间,否则返回{"error":"wrong status code (should be between 200 and 530)"}。
七、请求管理 API
7.1 端点:列出会话全部请求
| 属性 | 值 |
|---|---|
| 方法 | GET |
| URL | /api/session/{session_uuid}/requests |
| 成功 | 200 OK + JSON 数组(按接收时间倒序) |
| 会话不存在 | 404 + {"error":"session not found"} |
实测示例
curl -s http://localhost:8080/api/session/a1b2c3d4-e5f6-7890-abcd-ef1234567890/requests | python3 -m json.tool
# [
# {
# "captured_at_unix_milli": 1793088587703,
# "client_address": "10.89.56.1",
# "headers": [
# {"name": "Accept", "value": "*/*"},
# {"name": "Content-Length", "value": "28"},
# {"name": "Content-Type", "value": "application/json"},
# {"name": "User-Agent", "value": "curl/8.18.0"}
# ],
# "method": "POST",
# "request_payload_base64": "eyJoZWxsbyI6IndvcmxkIiwiY291bnQiOjQyfQ==",
# "url": "http://localhost:8080/a1b2c3d4-e5f6-7890-abcd-ef1234567890/orders/created",
# "uuid": "1a1a69d7-63c8-4b70-84d8-59b669933e5b"
# }
# ]
| 字段 | 类型 | 说明 |
|---|---|---|
uuid | string | 本次请求唯一标识 |
method | string | HTTP 方法 |
url | string | 完整请求 URL |
client_address | string | 客户端 IP(代理场景为最后一跳) |
captured_at_unix_milli | int64 | 接收时间(Unix 毫秒) |
headers | array | 请求头列表(每个含 name/value) |
request_payload_base64 | string | 请求体(base64 编码),空请求为 "" |
Base64 解码请求体
echo "eyJoZWxsbyI6IndvcmxkIiwiY291bnQiOjQyfQ==" | base64 -d
# {"hello":"world","count":42}
7.2 端点:清空会话全部请求
| 属性 | 值 |
|---|---|
| 方法 | DELETE |
| URL | /api/session/{session_uuid}/requests |
| 成功 | 200 OK + {"success":true} |
| 会话不存在 | 404 + {"error":"session not found"} |
实测示例
curl -s -X DELETE http://localhost:8080/api/session/a1b2c3d4-e5f6-7890-abcd-ef1234567890/requests
# {"success":true}
# 确认已清空
curl -s http://localhost:8080/api/session/a1b2c3d4-e5f6-7890-abcd-ef1234567890/requests
# []
7.3 端点:获取单条请求
| 属性 | 值 |
|---|---|
| 方法 | GET |
| URL | /api/session/{session_uuid}/requests/{request_uuid} |
| 成功 | 200 OK + JSON 对象 |
示例
curl -s "http://localhost:8080/api/session/a1b2c3d4-e5f6-7890-abcd-ef1234567890/requests/1a1a69d7-63c8-4b70-84d8-59b669933e5b"
# {"captured_at_unix_milli":1793088587703,"client_address":"10.89.56.1","headers":[...],"method":"POST","request_payload_base64":"eyJoZWxsbyI6IndvcmxkIiwiY291bnQiOjQyfQ==","url":"...","uuid":"1a1a69d7-..."}
7.4 端点:删除单条请求
| 属性 | 值 |
|---|---|
| 方法 | DELETE |
| URL | /api/session/{session_uuid}/requests/{request_uuid} |
| 成功 | 204 No Content(或 {"success":true}) |
八、系统信息 API
8.1 端点:获取当前版本
curl -s http://localhost:8080/api/version
# {"version":"2.3.0"}
8.2 端点:查询 GitHub 最新版
curl -s http://localhost:8080/api/version/latest
# {"version":"2.3.0"}
# (需要外网访问 github.com;失败返回 {"error":"failed to fetch the latest version: ..."})
8.3 端点:获取系统设置
curl -s http://localhost:8080/api/settings | python3 -m json.tool
# {
# "limits": {
# "max_request_body_size": 0, ← 单请求体上限(字节),0 = 不限
# "max_requests": 128, ← 每会话最大请求数
# "session_ttl": 604800 ← 会话 TTL(秒),604800 = 7 天
# },
# "tunnel": {
# "enabled": false ← ngrok 隧道是否启用
# }
# }
九、健康探针 API
9.1 Liveness Probe(存活)
# GET
curl -s http://localhost:8080/healthz
# OK
# HEAD
curl -s -I http://localhost:8080/healthz | head -3
# HTTP/1.1 200 OK
# Content-Type: text/plain; charset=utf-8
# Content-Length: 2
9.2 Readiness Probe(就绪)
curl -s http://localhost:8080/ready
# OK
9.3 K8s 部署模板片段
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 10
periodSeconds: 30
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
十、WebSocket 实时订阅
10.1 说明
/live 端点提供 WebSocket 连接,当有新 Webhook 请求到达已存在的会话时,服务端会实时推送通知。与 GET /api/session/{uuid}/requests 轮询相比,WebSocket 具有低延迟和低开销的优势。
10.2 端点详情
| 属性 | 值 |
|---|---|
| URL | ws://host:8080/live |
| 升级 | HTTP 1.1 → WebSocket 13 |
| 协议 | RFC 6455 |
10.3 Node.js 示例
// npm i ws
const WebSocket = require('ws');
const ws = new WebSocket('ws://localhost:8080/live');
ws.on('open', () => {
console.log('WebSocket connected');
// 发送感兴趣的会话 UUID(可多次发送订阅多个)
ws.send(JSON.stringify({
action: 'subscribe',
session_uuid: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890'
}));
});
ws.on('message', (data) => {
const msg = JSON.parse(data);
console.log('New request:', msg);
// {"session_uuid":"a1b2c3d4-...","request_uuid":"1a1a69d7-...","method":"POST","url":"..."}
});
ws.on('error', (err) => {
console.error('WebSocket error:', err);
});
10.4 测试步骤
# 终端 1:建立 WebSocket 连接
curl -s -N \
-H "Upgrade: websocket" \
-H "Connection: Upgrade" \
-H "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==" \
-H "Sec-WebSocket-Version: 13" \
http://localhost:8080/live
# 终端 2:发送 webhook 触发推送
curl -s -X POST http://localhost:8080/a1b2c3d4-e5f6-7890-abcd-ef1234567890/live-test \
-H "Content-Type: application/json" -d '{"event":"pushed"}'
# 终端 1 应在 100ms 内收到推送
十一、错误码速查
| HTTP 状态码 | 场景 | 错误体 |
|---|---|---|
| 200 | 成功 | 业务对象(JSON)或空 |
| 204 | 成功删除 | 空 |
| 400 | 请求参数错误 | {"error":"wrong status code (should be between 200 and 530)"} |
| 404 | 会话不存在 / 路由不存在 | {"error":"session not found"} 或 {"error":"not found"} |
| 500 | 服务器内部错误 | {"error":"..."} |
实测 404
curl -s -w "\nHTTP %{http_code}\n" http://localhost:8080/api/session/ffffffff-ffff-ffff-ffff-ffffffffffff
# {"error":"session not found"}
# HTTP 404
curl -s -w "\nHTTP %{http_code}\n" http://localhost:8080/api/unknown
# {"error":"not found"}
# HTTP 404
实测 400(创建会话时状态码越界)
curl -s -X POST http://localhost:8080/api/session \
-H "Content-Type: application/json" \
-d '{"status_code":999}'
# {"error":"wrong status code (should be between 200 and 530)"}
十二、自动化测试集成示例
以下 Python 脚本演示了完整的自动化测试流程——创建测试会话、发送 webhook、验证接收、清理:
import json
import subprocess
import base64
BASE = "http://localhost:8080"
def curl(method, path, data=None):
cmd = ["curl", "-s", "-X", method, f"{BASE}{path}", "-H", "Content-Type: application/json"]
if data:
cmd += ["-d", json.dumps(data)]
return json.loads(subprocess.check_output(cmd))
# Step 1: 发送 webhook(自动创建会话)
SESSION = "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
PAYLOAD = {"event": "push", "ref": "refs/heads/main", "sender": "test-bot"}
subprocess.run([
"curl", "-s", "-X", "POST", f"{BASE}/{SESSION}/github/push",
"-H", "Content-Type: application/json",
"-d", json.dumps(PAYLOAD)
], check=True)
# Step 2: 查询并验证
reqs = curl("GET", f"/api/session/{SESSION}/requests")
assert len(reqs) > 0, "No requests captured!"
assert reqs[0]["method"] == "POST"
assert reqs[0]["url"].endswith(f"/{SESSION}/github/push")
body = base64.b64decode(reqs[0]["request_payload_base64"]).decode()
body_json = json.loads(body)
assert body_json["event"] == "push"
print(f"✓ Webhook captured: {reqs[0]['uuid']}, payload verified")
# Step 3: 清理
curl("DELETE", f"/api/session/{SESSION}/requests")
curl("DELETE", f"/api/session/{SESSION}")
print("✓ Cleanup complete")
十三、常见问题(FAQ)
Q1:/api/version/latest 超时或报错?
该端点需要访问 https://github.com 检查最新 Release。网络受限环境会超时(默认 15s)。内网环境跳过此调用即可。
Q2:会话被 session_ttl 过期后,API 会返回什么?
已过期会话在查询时返回 {"error":"session not found"} 和 404。WebSocket 订阅不会自动清理过期会话,需要客户端按需维护。
Q3:请求体超过 max_request_body_size 会怎样?
STORAGE_DRIVER=memory:超出大小的请求体被拒绝(HTTP 413 或类似状态码)- 注意:该限制不会阻止 Webhook 接收,只会丢弃过大的请求体内容(body 字段为空或截断)
Q4:WebSocket /live 不支持 Token 认证?
不支持。如需安全 WebSocket 连接,前置反向代理(Nginx)做 Basic Auth 或 IP 白名单。
Q5:DELETE 会话后,WebSocket 订阅会报错吗? 不会报错,但服务端不再推送该会话的请求(因为会话已不存在)。客户端需要自行维护会话订阅状态。
Q6:多个实例部署时 API 有什么不同?
API 本身不变——只要 Storage 和 Pub/Sub 都指向同一个 Redis,请求会被正确捕获和推送。注意:GET /api/settings 返回的是实例自身的配置,多实例间可能略有差异。
十四、参考链接
- 源码仓库:https://github.com/tarampampam/webhook-tester
- Go Packages(类型定义):https://pkg.go.dev/gh.tarampamp.am/webhook-tester/v2@v2.3.0/internal/http/openapi
- WebSocket RFC 6455:https://datatracker.ietf.org/doc/html/rfc6455
- REST API 设计规范(参考):Fielding Dissertation