Files
ai-exchange/scripts/run_webhook_capture.py
2026-05-11 23:37:47 +08:00

63 lines
1.9 KiB
Python

from __future__ import annotations
from pathlib import Path
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
import json
import os
import sys
ROOT = Path(__file__).resolve().parents[1]
if str(ROOT) not in sys.path:
sys.path.insert(0, str(ROOT))
CAPTURE_FILE = ROOT / "tmp_webhook_capture.jsonl"
class CaptureHandler(BaseHTTPRequestHandler):
def do_POST(self) -> None:
try:
length = int(self.headers.get("Content-Length", "0"))
except ValueError:
length = 0
raw_body = self.rfile.read(length) if length else b""
record = {
"path": self.path,
"headers": {key: value for key, value in self.headers.items()},
"body": _decode_json(raw_body),
}
with CAPTURE_FILE.open("a", encoding="utf-8") as handle:
handle.write(json.dumps(record, ensure_ascii=False) + "\n")
payload = json.dumps({"ok": True, "captured": True}).encode("utf-8")
self.send_response(200)
self.send_header("Content-Type", "application/json; charset=utf-8")
self.send_header("Content-Length", str(len(payload)))
self.send_header("x-request-id", "local-capture")
self.end_headers()
self.wfile.write(payload)
def log_message(self, format: str, *args) -> None:
return
def main(env=None) -> int:
env = os.environ if env is None else env
host = env.get("WEBHOOK_CAPTURE_HOST", "127.0.0.1")
port = int(env.get("WEBHOOK_CAPTURE_PORT", "8787"))
server = ThreadingHTTPServer((host, port), CaptureHandler)
print(f"Webhook capture listening on http://{host}:{port}")
server.serve_forever()
return 0
def _decode_json(raw_body: bytes):
if not raw_body:
return {}
try:
return json.loads(raw_body.decode("utf-8"))
except Exception:
return {"raw": raw_body.decode("utf-8", errors="replace")}
if __name__ == "__main__":
raise SystemExit(main())