Skip to content

Latest commit

 

History

History
1338 lines (1035 loc) · 26.4 KB

File metadata and controls

1338 lines (1035 loc) · 26.4 KB

HookBridge REST API 文档

HookBridge 提供 23 个 REST 端点与 1 个 WebSocket 通道,覆盖健康检查、请求管理、重放、Mock、签名验证、转发记录与统计。

  • 基础路径:http(s)://<host>:<port>
  • 默认端口:9876
  • 响应格式:application/json; charset=utf-8
  • 时间字段:Unix 毫秒(整数)或 RFC3339(仅展示字段)

鉴权方式

HookBridge 管理 API 采用 Bearer Token + IP 白名单 双层鉴权。

Bearer Token

hookbridge.yaml 配置:

security:
  secret: "your-long-random-bearer-token"

调用管理 API 时携带:

Authorization: Bearer your-long-random-bearer-token

secret 为空时跳过 Token 校验(仅本地调试推荐)。

IP 白名单

security:
  ip_whitelist:
    - 10.0.0.0/8
    - 192.168.0.0/16
    - 203.0.113.42/32

支持 CIDR 语法。纯 IP 会自动补 /32(IPv4)或 /128(IPv6)。白名单为空时允许任意 IP。

鉴权生效范围

路径前缀 鉴权 说明
/api/* 所有管理 API
/health 健康检查(公开,供 LB 探活)
/metrics Prometheus 指标(公开,按需收紧)
/ws WebSocket(默认公开,建议反代时收紧)
其它任意路径 WebHook 接收路径,需对上游平台开放

鉴权失败响应

HTTP/1.1 401 Unauthorized
Content-Type: application/json; charset=utf-8

{
  "error": "unauthorized"
}

1. GET /health

健康检查(公开,供负载均衡探活)。

  • 鉴权:否
  • 请求参数:无
  • 说明:轻量探活,不查数据库,仅返回进程存活状态。

成功响应

HTTP/1.1 200 OK
Content-Type: application/json

{
  "ok": true,
  "version": "v1.0.0-final"
}

2. GET /metrics

Prometheus 格式指标(公开)。

  • 鉴权:否
  • 请求参数:无
  • 说明:返回 Prometheus 文本格式指标,包含请求数、延迟分位、存储行数、WebSocket 客户端数等。

成功响应

HTTP/1.1 200 OK
Content-Type: text/plain; version=0.0.4

# HELP hookbridge_requests_total Total received webhooks
# TYPE hookbridge_requests_total counter
hookbridge_requests_total 10234
hookbridge_requests_total{template="GitHub"} 3120
hookbridge_requests_total{template="Stripe"} 892

# HELP hookbridge_request_duration_seconds Request duration
# TYPE hookbridge_request_duration_seconds histogram
hookbridge_request_duration_seconds_bucket{le="0.001"} 8900
hookbridge_request_duration_seconds_bucket{le="0.01"} 10100
hookbridge_request_duration_seconds_bucket{le="0.1"} 10234
hookbridge_request_duration_seconds_bucket{le="+Inf"} 10234

# HELP hookbridge_storage_rows SQLite rows
# TYPE hookbridge_storage_rows gauge
hookbridge_storage_rows{table="requests"} 9821
hookbridge_storage_rows{table="replay_records"} 412

# HELP hookbridge_ws_clients WebSocket connected clients
# TYPE hookbridge_ws_clients gauge
hookbridge_ws_clients 3

3. GET /api/health

API 健康检查(需鉴权),返回版本与公网地址。

  • 鉴权:是
  • 请求参数:无

成功响应

HTTP/1.1 200 OK

{
  "ok": true,
  "public": "https://hook.example.com",
  "version": "v1.0.0-final"
}

失败响应

HTTP/1.1 401 Unauthorized

{
  "error": "unauthorized"
}

4. GET /api/templates

获取所有可用协议模板(内置 + 自定义)。

  • 鉴权:是
  • 请求参数:无

成功响应

HTTP/1.1 200 OK

{
  "templates": [
    {
      "name": "Stripe",
      "description": "Stripe 支付回调(含 Stripe-Signature 头)"
    },
    {
      "name": "GitHub",
      "description": "GitHub WebHook(X-GitHub-Event 头)"
    },
    {
      "name": "GitLab",
      "description": "GitLab WebHook(X-Gitlab-Event 头)"
    },
    {
      "name": "Gitee",
      "description": "Gitee WebHook(X-Gitee-Token 头)"
    },
    {
      "name": "Alipay",
      "description": "支付宝回调(Body 含 trade_status / notify_id)"
    },
    {
      "name": "WeChatPay",
      "description": "微信支付回调(XML 体含 appid/mch_id)"
    },
    {
      "name": "DingTalk",
      "description": "钉钉事件订阅(Body 含 EventType)"
    },
    {
      "name": "Feishu",
      "description": "飞书事件订阅(Header 含 X-Lark-Request-Timestamp)"
    },
    {
      "name": "WeCom",
      "description": "企业微信回调(XML 体含 ToUserName/Encrypt)"
    },
    {
      "name": "GB28181",
      "description": "GB28181 平台推流通知(自定义路径或 JSON 体)"
    },
    {
      "name": "HikvisionISAPI",
      "description": "海康 ISAPI 告警(XML 体含 EventNotificationAlert)"
    },
    {
      "name": "DahuaDSS",
      "description": "大华 DSS 回调(自定义路径或 JSON 体含 deviceId)"
    }
  ]
}

5. GET /api/requests

请求列表查询,支持分页与多维度过滤。

  • 鉴权:是
  • 请求参数(Query):
参数 类型 默认 说明
page int 1 页码(与 offset 二选一,page 优先)
size int 50 每页条数,最大 500
offset int 0 偏移量(与 page 二选一)
search string URL / Header / Body 模糊搜索
path string 精确匹配 path
method string 精确匹配 HTTP 方法(自动转大写)
content_type string 前缀匹配 Content-Type
ip string 精确匹配 RemoteIP
template string 精确匹配协议模板名
start int 0 起始时间(Unix 毫秒),0 表示不限制
end int 0 结束时间(Unix 毫秒),0 表示不限制

成功响应

HTTP/1.1 200 OK

{
  "total": 10234,
  "items": [
    {
      "id": "7c8f9a2b-1234-5678-9abc-def012345678",
      "method": "POST",
      "url": "/webhook",
      "path": "/webhook",
      "headers": {
        "Content-Type": "application/json",
        "X-GitHub-Event": "push"
      },
      "query": {},
      "body": "{\"ref\":\"refs/heads/main\",\"repo\":\"hookbridge/demo\"}",
      "content_type": "application/json",
      "remote_ip": "192.30.252.1",
      "user_agent": "GitHub-Hookshot/abc123",
      "created_at": "2026-07-26T10:23:45.123Z",
      "protocol_template": "GitHub",
      "status_code": 200,
      "response_body": "{\"ok\":true,\"msg\":\"HookBridge received\"}",
      "signature": "a1b2c3d4e5f6...",
      "duration_ms": 1
    }
  ],
  "limit": 50,
  "offset": 0
}

失败响应

HTTP/1.1 500 Internal Server Error

{
  "error": "query: database is closed"
}

6. GET /api/requests/{id}

请求详情,附带协议模板字段提取(命中模板时)。

  • 鉴权:是
  • 请求参数(Path):
参数 类型 说明
id string 请求 UUID

成功响应(命中模板时附带 fields)

HTTP/1.1 200 OK

{
  "request": {
    "id": "7c8f9a2b-1234-5678-9abc-def012345678",
    "method": "POST",
    "url": "/webhook",
    "path": "/webhook",
    "headers": {
      "Content-Type": "application/json",
      "X-GitHub-Event": "push",
      "X-GitHub-Delivery": "abc123",
      "X-Hub-Signature-256": "sha256=..."
    },
    "query": {},
    "body": "{\"ref\":\"refs/heads/main\",\"repository\":{\"full_name\":\"hookbridge/demo\"}}",
    "content_type": "application/json",
    "remote_ip": "192.30.252.1",
    "user_agent": "GitHub-Hookshot/abc123",
    "created_at": "2026-07-26T10:23:45.123Z",
    "protocol_template": "GitHub",
    "status_code": 200,
    "response_body": "{\"ok\":true,\"msg\":\"HookBridge received\"}",
    "signature": "a1b2c3d4e5f6...",
    "duration_ms": 1
  },
  "fields": {
    "event": "push",
    "delivery_id": "abc123",
    "ref": "refs/heads/main",
    "repo": "hookbridge/demo"
  }
}

成功响应(未命中模板时直接返回 request)

HTTP/1.1 200 OK

{
  "id": "7c8f9a2b-...",
  "method": "POST",
  "url": "/custom-hook",
  "path": "/custom-hook",
  "headers": { "...": "..." },
  "protocol_template": "",
  "..."
  : "..."
}

失败响应

HTTP/1.1 404 Not Found

{
  "error": "not found"
}

7. DELETE /api/requests/{id}

删除单条请求。

  • 鉴权:是
  • 请求参数(Path):
参数 类型 说明
id string 请求 UUID

成功响应

HTTP/1.1 200 OK

{
  "deleted": "7c8f9a2b-1234-5678-9abc-def012345678"
}

失败响应

HTTP/1.1 500 Internal Server Error

{
  "error": "delete: database is closed"
}

8. DELETE /api/requests

清空所有请求(不可恢复)。

  • 鉴权:是
  • 请求参数:无

成功响应

HTTP/1.1 200 OK

{
  "deleted": true
}

失败响应

HTTP/1.1 500 Internal Server Error

{
  "error": "delete all: database is closed"
}

9. POST /api/requests/{id}/replay

一键重放指定请求。

  • 鉴权:是
  • 请求参数(Path):
参数 类型 说明
id string 请求 UUID
  • 请求 Body:无

  • 说明:优先使用企业版重放引擎(带记录)。若配置了转发目标,则重放到第一个 forward target;否则回退到本地标记 replayed: false

成功响应

HTTP/1.1 200 OK

{
  "id": "replay-a1b2c3d4-...",
  "original_id": "7c8f9a2b-1234-5678-9abc-def012345678",
  "target_url": "https://upstream1.example.com/hook",
  "method": "POST",
  "status_code": 200,
  "response_body": "{\"ok\":true}",
  "duration_ms": 42,
  "created_at": 1785049600123,
  "success": true
}

失败响应

HTTP/1.1 404 Not Found

{
  "error": "not found"
}
HTTP/1.1 502 Bad Gateway

{
  "error": "dial tcp: connection refused",
  "id": "7c8f9a2b-..."
}

10. POST /api/requests/{id}/replay-modified

修改后重放:支持覆盖 method / headers / body / content_type / target_url。

  • 鉴权:是
  • 请求参数(Path):
参数 类型 说明
id string 请求 UUID
  • 请求 Body(JSON):
字段 类型 说明
target_url string 重放目标 URL,空则用原请求 URL
method string 覆盖 HTTP 方法
headers map[string]string 合并到原 headers(同名覆盖)
body string (base64) 或 []byte 覆盖请求体
content_type string 覆盖 Content-Type

请求示例

POST /api/requests/7c8f9a2b-.../replay-modified
Authorization: Bearer xxx
Content-Type: application/json

{
  "target_url": "https://staging.example.com/hook",
  "method": "PUT",
  "headers": {
    "X-Replay-Reason": "debug"
  },
  "body": "eyJyZWYiOiJyZWZzL2hlYWRzL2RldiJ9",
  "content_type": "application/json"
}

成功响应

HTTP/1.1 200 OK

{
  "id": "replay-b2c3d4e5-...",
  "original_id": "7c8f9a2b-...",
  "target_url": "https://staging.example.com/hook",
  "method": "PUT",
  "status_code": 200,
  "response_body": "{\"ok\":true}",
  "duration_ms": 38,
  "created_at": 1785049700123,
  "success": true
}

失败响应

HTTP/1.1 501 Not Implemented

{
  "error": "replay engine not enabled (enterprise feature)"
}

11. POST /api/replay/batch

批量重放,最多 500 条。

  • 鉴权:是
  • 请求 Body(JSON):
字段 类型 说明
ids []string 请求 ID 列表,最大 500
concurrent bool 是否并发执行(默认 false 串行)
opts ReplayOptions 重放选项(同 10),应用到所有请求

请求示例

POST /api/replay/batch
Authorization: Bearer xxx
Content-Type: application/json

{
  "ids": [
    "7c8f9a2b-...",
    "8d9e0b1c-...",
    "9e0f1c2d-..."
  ],
  "concurrent": true,
  "opts": {
    "target_url": "https://staging.example.com/hook"
  }
}

成功响应

HTTP/1.1 200 OK

{
  "total": 3,
  "success": 2,
  "failed": 1,
  "results": [
    {
      "original_id": "7c8f9a2b-...",
      "success": true,
      "status_code": 200,
      "duration_ms": 42
    },
    {
      "original_id": "8d9e0b1c-...",
      "success": true,
      "status_code": 200,
      "duration_ms": 38
    },
    {
      "original_id": "9e0f1c2d-...",
      "success": false,
      "error": "dial tcp: connection refused",
      "duration_ms": 5
    }
  ]
}

失败响应

HTTP/1.1 400 Bad Request

{
  "error": "too many ids (max 500)"
}

12. POST /api/requests/compare

对比两条请求,返回字段级差异。

  • 鉴权:是
  • 请求 Body(JSON):
字段 类型 说明
left_id string 左侧请求 ID
right_id string 右侧请求 ID

请求示例

POST /api/requests/compare
Authorization: Bearer xxx
Content-Type: application/json

{
  "left_id": "7c8f9a2b-...",
  "right_id": "8d9e0b1c-..."
}

成功响应

HTTP/1.1 200 OK

{
  "left": {
    "id": "7c8f9a2b-...",
    "method": "POST",
    "path": "/webhook",
    "headers": { "...": "..." }
  },
  "right": {
    "id": "8d9e0b1c-...",
    "method": "POST",
    "path": "/webhook",
    "headers": { "...": "..." }
  },
  "diffs": [
    {
      "field": "headers.X-GitHub-Delivery",
      "left": "abc123",
      "right": "def456"
    },
    {
      "field": "body.ref",
      "left": "refs/heads/main",
      "right": "refs/heads/dev"
    }
  ]
}

失败响应

HTTP/1.1 404 Not Found

{
  "error": "left not found"
}

13. GET /api/replay/records

查询重放记录列表。

  • 鉴权:是
  • 请求参数(Query):
参数 类型 默认 说明
original_id string 按原请求 ID 过滤
limit int 50 返回条数上限

成功响应

HTTP/1.1 200 OK

{
  "items": [
    {
      "id": "replay-a1b2c3d4-...",
      "original_id": "7c8f9a2b-...",
      "target_url": "https://upstream1.example.com/hook",
      "method": "POST",
      "status_code": 200,
      "response_body": "{\"ok\":true}",
      "duration_ms": 42,
      "created_at": 1785049600123,
      "success": true
    }
  ],
  "total": 1
}

失败响应

HTTP/1.1 500 Internal Server Error

{
  "error": "list replay records: database is closed"
}

14. GET /api/mock/rules

获取 Mock 规则列表。

  • 鉴权:是
  • 请求参数:无

成功响应

HTTP/1.1 200 OK

{
  "items": [
    {
      "id": 1,
      "name": "Stripe 成功回调",
      "enabled": true,
      "priority": 100,
      "match_path": "/stripe",
      "match_method": "POST",
      "match_header": null,
      "match_body": null,
      "response_status": 200,
      "response_body": "{\"id\":\"evt_mock_001\",\"object\":\"event\",\"type\":\"payment_intent.succeeded\"}",
      "response_headers": {
        "Content-Type": "application/json"
      },
      "delay_ms": 0,
      "created_at": 1785049600123,
      "updated_at": 1785049600123
    }
  ],
  "total": 1
}

失败响应

HTTP/1.1 500 Internal Server Error

{
  "error": "list mock rules: database is closed"
}

15. POST /api/mock/rules

创建 Mock 规则。

  • 鉴权:是
  • 请求 Body(JSON):
字段 类型 必填 说明
name string 规则名称
enabled bool 是否启用,默认 true
priority int 优先级(数字越大越先匹配),默认 0
match_path string 匹配路径(精确或正则)
match_method string 匹配 HTTP 方法
match_header map[string]string 匹配 header(值为正则)
match_body string 匹配 body(正则或关键字)
response_status int 响应状态码,默认 200
response_body string 响应体
response_headers map[string]string 响应头
delay_ms int 响应延迟毫秒,默认 0

请求示例

POST /api/mock/rules
Authorization: Bearer xxx
Content-Type: application/json

{
  "name": "GitHub push 事件",
  "enabled": true,
  "priority": 100,
  "match_path": "/github",
  "match_method": "POST",
  "match_header": {
    "X-GitHub-Event": "push"
  },
  "response_status": 200,
  "response_body": "{\"ok\":true}",
  "response_headers": {
    "Content-Type": "application/json"
  },
  "delay_ms": 100
}

成功响应

HTTP/1.1 201 Created

{
  "id": 2,
  "name": "GitHub push 事件",
  "enabled": true,
  "priority": 100,
  "match_path": "/github",
  "match_method": "POST",
  "match_header": {
    "X-GitHub-Event": "push"
  },
  "match_body": null,
  "response_status": 200,
  "response_body": "{\"ok\":true}",
  "response_headers": {
    "Content-Type": "application/json"
  },
  "delay_ms": 100,
  "created_at": 1785049700123,
  "updated_at": 1785049700123
}

失败响应

HTTP/1.1 400 Bad Request

{
  "error": "name required"
}

16. GET /api/mock/rules/{id}

获取单条 Mock 规则详情。

  • 鉴权:是
  • 请求参数(Path):
参数 类型 说明
id int 规则 ID

成功响应

HTTP/1.1 200 OK

{
  "id": 2,
  "name": "GitHub push 事件",
  "enabled": true,
  "priority": 100,
  "..."
}

失败响应

HTTP/1.1 400 Bad Request

{
  "error": "invalid id"
}
HTTP/1.1 404 Not Found

{
  "error": "not found"
}

17. PUT /api/mock/rules/{id}

更新 Mock 规则(全量覆盖)。

  • 鉴权:是
  • 请求参数(Path):同 16
  • 请求 Body(JSON):同 15 的字段(id 由路径指定,会被覆盖)

请求示例

PUT /api/mock/rules/2
Authorization: Bearer xxx
Content-Type: application/json

{
  "name": "GitHub push 事件(已禁用)",
  "enabled": false,
  "priority": 100,
  "match_path": "/github",
  "response_status": 200,
  "response_body": "{\"ok\":true}"
}

成功响应

HTTP/1.1 200 OK

{
  "id": 2,
  "name": "GitHub push 事件(已禁用)",
  "enabled": false,
  "..."
}

失败响应

HTTP/1.1 400 Bad Request

{
  "error": "invalid body: invalid character 'x' looking for beginning of value"
}

18. DELETE /api/mock/rules/{id}

删除 Mock 规则。

  • 鉴权:是
  • 请求参数(Path):同 16

成功响应

HTTP/1.1 200 OK

{
  "deleted": 2
}

失败响应

HTTP/1.1 400 Bad Request

{
  "error": "invalid id"
}

19. GET /api/signature/logs

查询签名验证日志。

  • 鉴权:是
  • 请求参数(Query):
参数 类型 默认 说明
limit int 50 返回条数上限

成功响应

HTTP/1.1 200 OK

{
  "items": [
    {
      "id": "siglog-a1b2c3d4-...",
      "request_id": "7c8f9a2b-...",
      "template": "Stripe",
      "algorithm": "hmac-sha256",
      "passed": true,
      "reason": "",
      "created_at": 1785049600123
    },
    {
      "id": "siglog-b2c3d4e5-...",
      "request_id": "8d9e0b1c-...",
      "template": "GitHub",
      "algorithm": "hmac-sha256",
      "passed": false,
      "reason": "signature mismatch: expected abc..., got def...",
      "created_at": 1785049600456
    }
  ],
  "total": 2
}

失败响应

HTTP/1.1 500 Internal Server Error

{
  "error": "list signature logs: database is closed"
}

20. GET /api/signature/verifiers

列出已注册的签名验证器名称。

  • 鉴权:是
  • 请求参数:无

成功响应

HTTP/1.1 200 OK

{
  "items": ["Stripe", "GitHub", "Alipay", "WeChatPay"],
  "total": 4
}

21. GET /api/forward/records

查询转发记录。

  • 鉴权:是
  • 请求参数(Query):
参数 类型 默认 说明
request_id string 按原请求 ID 过滤
limit int 50 返回条数上限

成功响应

HTTP/1.1 200 OK

{
  "items": [
    {
      "id": "fwd-a1b2c3d4-...",
      "request_id": "7c8f9a2b-...",
      "target": "https://upstream1.example.com/hook",
      "attempt": 1,
      "status_code": 200,
      "response_body": "{\"ok\":true}",
      "error": "",
      "duration_ms": 42,
      "success": 1,
      "created_at": 1785049600123
    },
    {
      "id": "fwd-b2c3d4e5-...",
      "request_id": "8d9e0b1c-...",
      "target": "https://upstream2.example.com/hook",
      "attempt": 3,
      "status_code": 0,
      "response_body": "",
      "error": "dial tcp: connection refused (after 3 retries)",
      "duration_ms": 15000,
      "success": 0,
      "created_at": 1785049600456
    }
  ],
  "total": 2
}

失败响应

HTTP/1.1 500 Internal Server Error

{
  "error": "list forward records: database is closed"
}

22. GET /api/stats

获取统计数据,按方法 / 状态码 / Content-Type / 来源 IP / 模板 / 24 小时分布聚合。

  • 鉴权:是
  • 请求参数:无
  • 说明:聚合统计基于最近 24 小时数据;total 字段为全量总数。

成功响应

HTTP/1.1 200 OK

{
  "total": 10234,
  "last_24h": 5421,
  "by_method": {
    "POST": 9821,
    "GET": 413
  },
  "by_status": {
    "200": 10200,
    "404": 34
  },
  "by_content_type": {
    "application/json": 8900,
    "application/x-www-form-urlencoded": 1000,
    "application/xml": 334
  },
  "by_remote_ip": {
    "192.30.252.1": 3120,
    "203.0.113.42": 2200,
    "127.0.0.1": 100
  },
  "by_template": {
    "GitHub": 3120,
    "Stripe": 892,
    "WeChatPay": 134,
    "unknown": 6088
  },
  "by_hour": {
    "09:00": 320,
    "10:00": 540,
    "11:00": 612,
    "12:00": 410,
    "13:00": 380,
    "14:00": 720
  }
}

失败响应

HTTP/1.1 500 Internal Server Error

{
  "error": "stats: database is closed"
}

23. WS /ws

WebSocket 实时推送通道,新请求到达时秒级推送给所有已连接客户端。

  • 鉴权:否(默认公开,建议反代时收紧)
  • 协议:WebSocket(RFC 6455)
  • 子协议:无
  • Origin:允许任意(社区版自托管调试场景)

连接示例

浏览器 JavaScript:

const ws = new WebSocket('ws://localhost:9876/ws');
ws.onmessage = (event) => {
  const msg = JSON.parse(event.data);
  console.log(msg.type, msg);
};

服务端推送消息格式

{
  "type": "request",
  "request": {
    "id": "7c8f9a2b-...",
    "method": "POST",
    "path": "/webhook",
    "headers": { "...": "..." },
    "body": "{\"ref\":\"refs/heads/main\"}",
    "protocol_template": "GitHub",
    "created_at": "2026-07-26T10:23:45.123Z",
    "duration_ms": 1
  },
  "parsed": {
    "format": "json",
    "fields": {
      "ref": "refs/heads/main"
    }
  },
  "is_dup": false,
  "timestamp": 1785049600123
}

心跳消息

服务端每 30 秒广播一次心跳:

{
  "type": "ping",
  "timestamp": 1785049630123
}

消息类型

type 触发条件 携带字段
request 收到新 WebHook 请求 request / parsed / is_dup
ping 心跳(每 30 秒) timestamp

客户端保活

  • 客户端读取超时 60 秒,超时未收到消息则断开
  • 服务端每 30 秒推送一次 ping,可作为保活信号
  • 客户端可发送任意消息保活(如空 JSON {}),服务端仅用于刷新读取死线
  • 服务端读取上限 8192 字节,超过则断开

连接限制

  • 单连接发送队列 64 条消息,满了则丢弃(避免慢客户端拖垮服务端)
  • 广播通道总缓冲 256 条,满了则丢弃
  • 注册 / 注销通道缓冲 8 个,避免注册洪峰阻塞主循环

通用错误响应

所有端点在鉴权失败时返回:

HTTP/1.1 401 Unauthorized

{
  "error": "unauthorized"
}

路径不存在时返回:

HTTP/1.1 404 Not Found

{
  "error": "not found",
  "path": "unknown/path"
}

方法不允许时返回:

HTTP/1.1 405 Method Not Allowed

{
  "error": "method not allowed"
}

服务端内部错误:

HTTP/1.1 500 Internal Server Error

{
  "error": "<错误详情>"
}

企业版功能未启用时(如重放引擎未注入):

HTTP/1.1 501 Not Implemented

{
  "error": "replay engine not enabled (enterprise feature)"
}