Files
blog-fuwari/feedback-api/main.py
T
2026-05-23 21:43:40 +08:00

71 lines
1.5 KiB
Python

import hashlib
from contextlib import asynccontextmanager
from fastapi import FastAPI, Request
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
from database import add_feedback, check_rate_limit, get_stats, init_db
class FeedbackIn(BaseModel):
url: str
choice: str
timestamp: str
RATE_LIMIT = 5
RATE_WINDOW = 3600
@asynccontextmanager
async def lifespan(app: FastAPI):
await init_db()
yield
app = FastAPI(lifespan=lifespan)
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_methods=["*"],
allow_headers=["*"],
)
def get_client_ip(request: Request) -> str:
cf_ip = request.headers.get("cf-connecting-ip")
if cf_ip:
return cf_ip
forwarded = request.headers.get("x-forwarded-for")
if forwarded:
return forwarded.split(",")[0].strip()
return request.client.host or "unknown"
@app.post("/api/feedback")
async def receive_feedback(body: FeedbackIn, request: Request):
ip = get_client_ip(request)
ip_hash = hashlib.sha256(ip.encode()).hexdigest()
if not await check_rate_limit(ip_hash, RATE_LIMIT, RATE_WINDOW):
await add_feedback(ip_hash, body.url, body.choice, body.timestamp)
return {"ok": True}
@app.get("/api/feedback/stats")
async def stats():
return await get_stats()
@app.get("/api/feedback/health")
async def health():
return {"status": "ok"}
if __name__ == "__main__":
import uvicorn
uvicorn.run("main:app", host="0.0.0.0", port=8005)