Spaces:
Sleeping
Sleeping
add rate limiter
Browse files
main.py
CHANGED
|
@@ -2,7 +2,9 @@ from typing import List, Dict, Any
|
|
| 2 |
import os
|
| 3 |
import shutil
|
| 4 |
import uuid
|
| 5 |
-
|
|
|
|
|
|
|
| 6 |
from fastapi.responses import HTMLResponse, JSONResponse
|
| 7 |
from fastapi.templating import Jinja2Templates
|
| 8 |
from fastapi.staticfiles import StaticFiles
|
|
@@ -48,9 +50,8 @@ app.mount("/static", StaticFiles(directory="./static", html=True), name="static"
|
|
| 48 |
app.add_middleware(SessionMiddleware, secret_key="audio-annotator-application")
|
| 49 |
templates = Jinja2Templates(directory="./templates")
|
| 50 |
|
| 51 |
-
# --- Utility Functions ---
|
| 52 |
-
|
| 53 |
|
|
|
|
| 54 |
def load_data_for_index(user_id: int, index: int) -> Dict[str, Any]:
|
| 55 |
"""Helper to safely fetch data for a given index."""
|
| 56 |
if not ANNOTATION_DATA[user_id]:
|
|
@@ -88,11 +89,31 @@ def serve_index_html(request: Request):
|
|
| 88 |
except FileNotFoundError:
|
| 89 |
return HTMLResponse(content="<h1>Server Error: index.html not found.</h1>", status_code=500)
|
| 90 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 91 |
|
| 92 |
# --- Routes ---
|
| 93 |
|
| 94 |
|
| 95 |
@app.get("/")
|
|
|
|
| 96 |
async def index(request: Request):
|
| 97 |
"""Serves the main application page by reading index.html."""
|
| 98 |
return serve_index_html(request)
|
|
|
|
| 2 |
import os
|
| 3 |
import shutil
|
| 4 |
import uuid
|
| 5 |
+
import time
|
| 6 |
+
from functools import wraps
|
| 7 |
+
from fastapi import FastAPI, Request, UploadFile, File, HTTPException, status
|
| 8 |
from fastapi.responses import HTMLResponse, JSONResponse
|
| 9 |
from fastapi.templating import Jinja2Templates
|
| 10 |
from fastapi.staticfiles import StaticFiles
|
|
|
|
| 50 |
app.add_middleware(SessionMiddleware, secret_key="audio-annotator-application")
|
| 51 |
templates = Jinja2Templates(directory="./templates")
|
| 52 |
|
|
|
|
|
|
|
| 53 |
|
| 54 |
+
# --- Utility Functions ---
|
| 55 |
def load_data_for_index(user_id: int, index: int) -> Dict[str, Any]:
|
| 56 |
"""Helper to safely fetch data for a given index."""
|
| 57 |
if not ANNOTATION_DATA[user_id]:
|
|
|
|
| 89 |
except FileNotFoundError:
|
| 90 |
return HTMLResponse(content="<h1>Server Error: index.html not found.</h1>", status_code=500)
|
| 91 |
|
| 92 |
+
def rate_limited(max_calls: int, time_frame:int):
|
| 93 |
+
"""
|
| 94 |
+
:param max_calls: Maximum number of calls allowed in the specified time frame.
|
| 95 |
+
:param time_frame: The time frame (in seconds) for which the limit applies.
|
| 96 |
+
:return: Decorator function.
|
| 97 |
+
"""
|
| 98 |
+
def decorator(func):
|
| 99 |
+
calls = []
|
| 100 |
+
|
| 101 |
+
@wraps(func)
|
| 102 |
+
async def wrapper(request: Request, *args, **kwargs):
|
| 103 |
+
now = time.time()
|
| 104 |
+
calls_in_time_frame = [call for call in calls if call > now - time_frame]
|
| 105 |
+
if len(calls_in_time_frame) > max_calls:
|
| 106 |
+
raise HTTPException(status_code=status.HTTP_429_TOO_MANY_REQUESTS, detail="Rate limit exceeded.")
|
| 107 |
+
calls.append(now)
|
| 108 |
+
return await func(request, *args, **kwargs)
|
| 109 |
+
return wrapper
|
| 110 |
+
return decorator
|
| 111 |
|
| 112 |
# --- Routes ---
|
| 113 |
|
| 114 |
|
| 115 |
@app.get("/")
|
| 116 |
+
@rate_limited(max_calls=10, time_frame=60)
|
| 117 |
async def index(request: Request):
|
| 118 |
"""Serves the main application page by reading index.html."""
|
| 119 |
return serve_index_html(request)
|