1Xayd1
(1xayd1)
July 10, 2025, 4:23pm
1
This is a system built on fastAPI it doesnt log anything nor saves any data, barebones json request handling.
Api endpoint:
http://c4.play2go.cloud:20894/api/webhooks/
How to use
replace:
discord.com/
with http://c4.play2go.cloud:20894/
Please contact me if the service goes down!
7 Likes
1Xayd1
(1xayd1)
July 10, 2025, 4:24pm
2
Source code
from fastapi import FastAPI, HTTPException, Request
from fastapi.middleware import Middleware
from fastapi.middleware.trustedhost import TrustedHostMiddleware
from fastapi.middleware.gzip import GZipMiddleware
from fastapi.requests import Request
from fastapi.responses import JSONResponse
from slowapi import Limiter
from slowapi.util import get_remote_address
from slowapi.errors import RateLimitExceeded
from pydantic import BaseModel, Field
import httpx
import uvicorn
from typing import Optional
import uuid
limiter = Limiter(key_func=get_remote_address)
MAX_REQUEST_SIZE = 1024 * 1024 # 1MB max
RATE_LIMIT = "2/second"
Hook = FastAPI(
title="SimpleHook",
description="A simplistic proxy for Discord webhooks",
version="1.1.0",
middleware=[
Middleware(TrustedHostMiddleware, allowed_hosts=["*"]),
Middleware(GZipMiddleware, minimum_size=1000),
]
)
Hook.state.limiter = limiter
@Hook.exception_handler(RateLimitExceeded)
async def rate_limit_exceeded_handler(request: Request, exc: RateLimitExceeded):
return JSONResponse(
status_code=429,
content={"detail": "Too many requests. Please try again later."},
headers={"Retry-After": str(exc.retry_after)}
)
class WebhookPayload(BaseModel):
content: Optional[str] = Field(None, max_length=2000)
username: Optional[str] = Field(None, max_length=80)
avatar_url: Optional[str] = Field(None, max_length=512)
tts: Optional[bool] = False
embeds: Optional[list] = None
allowed_mentions: Optional[dict] = None
components: Optional[list] = None
flags: Optional[int] = None
thread_name: Optional[str] = Field(None, max_length=100)
@Hook.post("/api/webhooks/{webhook_id}/{webhook_token}")
@limiter.limit(RATE_LIMIT)
async def proxy_webhook(
request: Request,
webhook_id: str,
webhook_token: str,
payload: WebhookPayload
):
request_size = int(request.headers.get('content-length', 0))
if request_size > MAX_REQUEST_SIZE:
raise HTTPException(
status_code=413,
detail=f"Payload too large. Max allowed: {MAX_REQUEST_SIZE} bytes"
)
request_id = str(uuid.uuid4())[:8]
discord_url = f"https://discord.com/api/webhooks/{webhook_id}/{webhook_token}"
data = payload.dict(exclude_unset=True)
if len(str(data)) > MAX_REQUEST_SIZE:
raise HTTPException(
status_code=413,
detail="Payload too large after processing"
)
try:
async with httpx.AsyncClient(timeout=10.0) as client:
response = await client.post(
discord_url,
json=data,
headers={
"Content-Type": "application/json",
"User-Agent": f"SimpleHook/1.0 (+https://{request.url.netloc})"
}
)
if response.is_error:
raise HTTPException(
status_code=response.status_code,
detail=f"Discord API returned error: {response.text}"
)
return {
"status": "success",
"request_id": request_id,
"discord_status": response.status_code
}
except httpx.RequestError as e:
raise HTTPException(
status_code=500,
detail=f"Failed to reach Discord API: {str(e)}"
)
@Hook.get("/")
async def read_root(request: Request):
return {
"message": "SimpleHook is running",
"usage": "POST /webhook/{webhook_id}/{webhook_token} with Discord webhook payload"
}
if __name__ == "__main__":
uvicorn.run(
Hook,
host="0.0.0.0",
port=20894,
timeout_keep_alive=30
)
Nothing special! It’s basic json post request forwarding!
1Xayd1
(1xayd1)
July 10, 2025, 4:28pm
3
Some more information:
I have disabled logging on my server in the hosting, you’re safe from anyone using your webhooks.
I’m paying myself for the hosting.
if you have any problems accessing the current port i gave, i have multiple ports to spare.
P.S
As to why i decided to make it now: the lewi’s webhook proxy has been ddosed, my friend told me about this, and since i have resources and time to spare here’s the outcome
2 Likes
1Xayd1
(1xayd1)
July 10, 2025, 5:49pm
4
Update V1.1
Added basic security to prevent from spamming proxy with massive payloads. The current ratelimit is 2/second i will adjust it if someone wants to use proxy more.
Source code is updated
1Xayd1
(1xayd1)
July 13, 2025, 9:02am
5
Hi new update i purchased multiple ports and will be forwarding all the requests from those now
2 Likes
I love how simple this is and it’s written in Python! A couple of questions for you:
Do you ever plan on putting it on GitHub instead of having a file in your devforum post?
Is caching/storing your requests and ratelimit information always going to be in the file or do you plan on storing them in Redis or MongoDB?