Spaces:
Sleeping
Sleeping
Carlos
Security hardening: SSRF validation, XSS escapes, rate limiting, proxy default 127.0.0.1, path traversal, webhook validation, security headers
b6ba216 | import time | |
| from collections import defaultdict | |
| from fastapi import HTTPException, Request | |
| from starlette.middleware.base import BaseHTTPMiddleware | |
| class RateLimitMiddleware(BaseHTTPMiddleware): | |
| def __init__(self, app, max_requests: int = 60, window_seconds: int = 60): | |
| super().__init__(app) | |
| self.max_requests = max_requests | |
| self.window_seconds = window_seconds | |
| self.requests: dict[str, list[float]] = defaultdict(list) | |
| async def dispatch(self, request: Request, call_next): | |
| if request.url.path in ("/api/health", "/static/", "/"): | |
| return await call_next(request) | |
| client_ip = request.client.host if request.client else "unknown" | |
| now = time.monotonic() | |
| cutoff = now - self.window_seconds | |
| self.requests[client_ip] = [t for t in self.requests[client_ip] if t > cutoff] | |
| if len(self.requests[client_ip]) >= self.max_requests: | |
| raise HTTPException(status_code=429, detail="Rate limit exceeded") | |
| self.requests[client_ip].append(now) | |
| return await call_next(request) | |