EXAM_RAG_API / webhook.py
MinaNasser's picture
1st
1bc3f18
from fastapi import FastAPI, Request
from fastapi.responses import HTMLResponse, RedirectResponse
import json
from datetime import datetime
app = FastAPI()
# In-memory storage
webhook_logs = []
@app.post("/webhook")
async def webhook(request: Request):
body = await request.body()
try:
body_json = json.loads(body)
body_pretty = json.dumps(body_json, indent=2)
except Exception:
body_pretty = body.decode("utf-8", errors="ignore")
webhook_logs.insert(0, {
"time": datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S UTC"),
"headers": dict(request.headers),
"body": body_pretty
})
del webhook_logs[50:]
return {"status": "ok"}
@app.post("/clear")
async def clear_logs():
webhook_logs.clear()
return RedirectResponse("/", status_code=303)
@app.get("/", response_class=HTMLResponse)
async def dashboard():
items = ""
for i, log in enumerate(webhook_logs):
items += f"""
<div class="entry">
<div class="entry-header">
<span class="badge">#{i + 1}</span>
<span class="time">{log["time"]}</span>
</div>
<details>
<summary>Headers</summary>
<pre>{json.dumps(log["headers"], indent=2)}</pre>
</details>
<details open>
<summary>Body</summary>
<pre>{log["body"]}</pre>
</details>
</div>
"""
html = f"""
<!DOCTYPE html>
<html>
<head>
<title>Webhook Viewer</title>
<meta http-equiv="refresh" content="3">
<style>
body {{
margin: 0;
font-family: system-ui, -apple-system, BlinkMacSystemFont;
background: #0b1020;
color: #e5e7eb;
}}
header {{
position: sticky;
top: 0;
background: #020617;
padding: 15px 20px;
border-bottom: 1px solid #1e293b;
display: flex;
justify-content: space-between;
align-items: center;
}}
header h1 {{
margin: 0;
font-size: 20px;
}}
.controls {{
display: flex;
gap: 10px;
align-items: center;
}}
.count {{
background: #1e293b;
padding: 4px 10px;
border-radius: 999px;
font-size: 12px;
}}
button {{
background: #dc2626;
border: none;
color: white;
padding: 6px 12px;
border-radius: 6px;
cursor: pointer;
font-size: 13px;
}}
button:hover {{
background: #b91c1c;
}}
main {{
padding: 20px;
}}
.entry {{
background: #020617;
border: 1px solid #1e293b;
border-radius: 10px;
padding: 15px;
margin-bottom: 16px;
}}
.entry-header {{
display: flex;
gap: 10px;
align-items: center;
margin-bottom: 10px;
}}
.badge {{
background: #2563eb;
color: white;
padding: 3px 8px;
border-radius: 6px;
font-size: 12px;
}}
.time {{
font-size: 12px;
color: #94a3b8;
}}
details summary {{
cursor: pointer;
font-weight: 600;
margin: 8px 0;
}}
pre {{
background: #020617;
border: 1px solid #1e293b;
padding: 10px;
border-radius: 6px;
overflow-x: auto;
color: #38bdf8;
font-size: 13px;
}}
.empty {{
text-align: center;
color: #64748b;
margin-top: 50px;
}}
</style>
</head>
<body>
<header>
<h1>📡 Webhook Viewer</h1>
<div class="controls">
<span class="count">{len(webhook_logs)} requests</span>
<form method="post" action="/clear">
<button type="submit">Clear</button>
</form>
</div>
</header>
<main>
{items if items else "<p class='empty'>No webhooks received yet</p>"}
</main>
</body>
</html>
"""
return html