63 lines
1.9 KiB
Python
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())
|