Spaces:
Running
Running
risunobushi
commited on
Commit
·
c71d616
1
Parent(s):
10136fd
Add IP-based rate limiting (30 requests/hour) and contact info, update YouTube link
Browse files
app.py
CHANGED
@@ -13,6 +13,7 @@ from typing import Tuple, Optional
|
|
13 |
import requests
|
14 |
from dotenv import load_dotenv
|
15 |
from PIL import Image
|
|
|
16 |
|
17 |
import gradio as gr
|
18 |
from supabase import create_client, Client
|
@@ -74,6 +75,31 @@ except Exception as exc: # noqa: BLE001
|
|
74 |
print(f"[startup] Bucket check/create raised {exc!r}. Continuing…")
|
75 |
|
76 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
77 |
# -----------------------------------------------------------------------------
|
78 |
# Helper functions
|
79 |
# -----------------------------------------------------------------------------
|
@@ -196,9 +222,14 @@ def _public_storage_url(path: str) -> str:
|
|
196 |
# Main generate function
|
197 |
# -----------------------------------------------------------------------------
|
198 |
|
199 |
-
def generate(base_img: Image.Image, garment_img: Image.Image, workflow_choice: str) -> Image.Image:
|
200 |
if base_img is None or garment_img is None:
|
201 |
raise gr.Error("Please provide both images.")
|
|
|
|
|
|
|
|
|
|
|
202 |
|
203 |
# 1. Persist both images to Supabase storage
|
204 |
job_id = str(uuid.uuid4())
|
|
|
13 |
import requests
|
14 |
from dotenv import load_dotenv
|
15 |
from PIL import Image
|
16 |
+
from collections import defaultdict, deque
|
17 |
|
18 |
import gradio as gr
|
19 |
from supabase import create_client, Client
|
|
|
75 |
print(f"[startup] Bucket check/create raised {exc!r}. Continuing…")
|
76 |
|
77 |
|
78 |
+
# -----------------------------------------------------------------------------
|
79 |
+
# Rate Limiting
|
80 |
+
# -----------------------------------------------------------------------------
|
81 |
+
|
82 |
+
# Rate limiter: 30 requests per IP per hour
|
83 |
+
RATE_LIMIT_REQUESTS = 30
|
84 |
+
RATE_LIMIT_WINDOW = 3600 # 1 hour in seconds
|
85 |
+
request_tracker = defaultdict(deque)
|
86 |
+
|
87 |
+
def check_rate_limit(client_ip: str) -> bool:
|
88 |
+
"""Check if IP has exceeded rate limit. Returns True if allowed, False if blocked."""
|
89 |
+
current_time = time.time()
|
90 |
+
user_requests = request_tracker[client_ip]
|
91 |
+
|
92 |
+
# Remove requests outside the time window
|
93 |
+
while user_requests and current_time - user_requests[0] > RATE_LIMIT_WINDOW:
|
94 |
+
user_requests.popleft()
|
95 |
+
|
96 |
+
# Check if under limit
|
97 |
+
if len(user_requests) < RATE_LIMIT_REQUESTS:
|
98 |
+
user_requests.append(current_time)
|
99 |
+
return True
|
100 |
+
|
101 |
+
return False
|
102 |
+
|
103 |
# -----------------------------------------------------------------------------
|
104 |
# Helper functions
|
105 |
# -----------------------------------------------------------------------------
|
|
|
222 |
# Main generate function
|
223 |
# -----------------------------------------------------------------------------
|
224 |
|
225 |
+
def generate(base_img: Image.Image, garment_img: Image.Image, workflow_choice: str, request: gr.Request) -> Image.Image:
|
226 |
if base_img is None or garment_img is None:
|
227 |
raise gr.Error("Please provide both images.")
|
228 |
+
|
229 |
+
# Rate limiting check
|
230 |
+
client_ip = request.client.host if request and request.client else "unknown"
|
231 |
+
if not check_rate_limit(client_ip):
|
232 |
+
raise gr.Error("Rate limit exceeded. Please try again later (30 requests per hour limit).")
|
233 |
|
234 |
# 1. Persist both images to Supabase storage
|
235 |
job_id = str(uuid.uuid4())
|