1
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
import re
|
||||
|
||||
from fastapi import Request, Response
|
||||
from starlette.middleware.base import BaseHTTPMiddleware, RequestResponseEndpoint
|
||||
from starlette.responses import JSONResponse
|
||||
|
||||
from app.config import settings
|
||||
|
||||
BLOCKED_UA_PATTERNS = [
|
||||
re.compile(r"(?i)(curl|wget|python-requests|scrapy|httpx|go-http-client|java/)"),
|
||||
]
|
||||
|
||||
|
||||
class AntiCrawlerMiddleware(BaseHTTPMiddleware):
|
||||
async def dispatch(
|
||||
self, request: Request, call_next: RequestResponseEndpoint
|
||||
) -> Response:
|
||||
# Skip health/docs
|
||||
if request.url.path in ("/health", "/api-docs", "/openapi.json", "/api-redoc"):
|
||||
return await call_next(request)
|
||||
|
||||
# Skip callback endpoints
|
||||
if request.url.path.startswith("/api/callbacks/"):
|
||||
return await call_next(request)
|
||||
|
||||
user_agent = request.headers.get("user-agent", "")
|
||||
|
||||
# Block empty User-Agent
|
||||
if not user_agent:
|
||||
return JSONResponse(status_code=403, content={"detail": "Forbidden"})
|
||||
|
||||
# Block known bot User-Agents (unless they have an API key)
|
||||
api_key = request.headers.get("x-api-key")
|
||||
if not api_key:
|
||||
for pattern in BLOCKED_UA_PATTERNS:
|
||||
if pattern.search(user_agent):
|
||||
return JSONResponse(
|
||||
status_code=403, content={"detail": "Forbidden"}
|
||||
)
|
||||
|
||||
return await call_next(request)
|
||||
Reference in New Issue
Block a user