Spaces:
Running
Running
Upload folder using huggingface_hub
Browse files
README.md
CHANGED
@@ -1,12 +1,12 @@
|
|
|
|
1 |
---
|
2 |
-
title:
|
3 |
-
emoji:
|
4 |
-
colorFrom:
|
5 |
-
colorTo:
|
6 |
sdk: gradio
|
7 |
sdk_version: 5.43.1
|
8 |
-
app_file:
|
9 |
pinned: false
|
|
|
10 |
---
|
11 |
-
|
12 |
-
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
|
|
1 |
+
|
2 |
---
|
3 |
+
title: rate_limit_main
|
4 |
+
emoji: π₯
|
5 |
+
colorFrom: indigo
|
6 |
+
colorTo: indigo
|
7 |
sdk: gradio
|
8 |
sdk_version: 5.43.1
|
9 |
+
app_file: run.py
|
10 |
pinned: false
|
11 |
+
hf_oauth: true
|
12 |
---
|
|
|
|
requirements.txt
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
1 |
+
gradio-client @ git+https://github.com/gradio-app/gradio@e16e45c57d0293dd82b40c6ba6260100544937f3#subdirectory=client/python
|
2 |
+
https://gradio-pypi-previews.s3.amazonaws.com/e16e45c57d0293dd82b40c6ba6260100544937f3/gradio-5.43.1-py3-none-any.whl
|
run.ipynb
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: rate_limit"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "from datetime import datetime, timedelta\n", "from collections import defaultdict\n", "import threading\n", "\n", "rate_limit_data = defaultdict(list)\n", "lock = threading.Lock()\n", "\n", "UNAUTH_RATE_LIMIT = 3\n", "AUTH_RATE_LIMIT = 30\n", "RATE_LIMIT_WINDOW = 60\n", "\n", "def clean_old_entries(user_id):\n", " \"\"\"Remove entries older than the rate limit window\"\"\"\n", " current_time = datetime.now()\n", " cutoff_time = current_time - timedelta(seconds=RATE_LIMIT_WINDOW)\n", " rate_limit_data[user_id] = [\n", " timestamp for timestamp in rate_limit_data[user_id]\n", " if timestamp > cutoff_time\n", " ]\n", "\n", "def get_user_identifier(profile: gr.OAuthProfile | None, request: gr.Request) -> tuple[str, bool]:\n", " \"\"\"Get user identifier and whether they're authenticated\"\"\"\n", " if profile is not None:\n", " return profile.username, True\n", " else:\n", " if request:\n", " return f\"ip_{request.client.host}\", False\n", " return \"ip_unknown\", False\n", "\n", "def check_rate_limit(user_id: str, is_authenticated: bool) -> tuple[bool, int, int]:\n", " \"\"\"\n", " Check if user has exceeded rate limit\n", " Returns: (can_proceed, clicks_used, max_clicks)\n", " \"\"\"\n", " with lock:\n", " clean_old_entries(user_id)\n", " \n", " max_clicks = AUTH_RATE_LIMIT if is_authenticated else UNAUTH_RATE_LIMIT\n", " clicks_used = len(rate_limit_data[user_id])\n", " \n", " can_proceed = clicks_used < max_clicks\n", " \n", " return can_proceed, clicks_used, max_clicks\n", "\n", "def add_click(user_id: str):\n", " \"\"\"Add a click timestamp for the user\"\"\"\n", " with lock:\n", " rate_limit_data[user_id].append(datetime.now())\n", "\n", "def update_status(profile: gr.OAuthProfile | None, request: gr.Request) -> str:\n", " \"\"\"Update the status message showing current rate limit info\"\"\"\n", " user_id, is_authenticated = get_user_identifier(profile, request)\n", " _, clicks_used, max_clicks = check_rate_limit(user_id, is_authenticated)\n", " \n", " if is_authenticated:\n", " return f\"\u2705 You are logged in as '{profile.username}'. You have clicked {clicks_used} times this minute. You have {max_clicks} total clicks per minute.\" # type: ignore\n", " else:\n", " return f\"\u26a0\ufe0f You are not logged in. You have clicked {clicks_used} times this minute. You have {max_clicks} total clicks per minute.\"\n", "\n", "def run_action(profile: gr.OAuthProfile | None, request: gr.Request) -> tuple[str, str]:\n", " \"\"\"Handle the run button click with rate limiting\"\"\"\n", " user_id, is_authenticated = get_user_identifier(profile, request)\n", " can_proceed, clicks_used, max_clicks = check_rate_limit(user_id, is_authenticated)\n", " \n", " if not can_proceed:\n", " result = f\"\u274c Rate limit exceeded! You've used all {max_clicks} clicks for this minute. Please wait before trying again.\"\n", " status = update_status(profile, request)\n", " return result, status\n", " \n", " add_click(user_id)\n", " \n", " _, new_clicks_used, _ = check_rate_limit(user_id, is_authenticated)\n", " \n", " result = f\"\u2705 Action executed successfully! (Click #{new_clicks_used})\"\n", " status = update_status(profile, request)\n", " \n", " return result, status\n", "\n", "with gr.Blocks(title=\"Rate Limiting Demo\") as demo:\n", " gr.Markdown(\"# Rate Limiting Demo App\")\n", " gr.Markdown(\"This app demonstrates rate limiting based on authentication status.\")\n", " \n", " gr.LoginButton()\n", " \n", " status_text = gr.Markdown(\"Loading status...\")\n", " \n", " with gr.Row():\n", " run_btn = gr.Button(\"\ud83d\ude80 Run Action\", variant=\"primary\", scale=1)\n", " \n", " result_text = gr.Markdown(\"\")\n", " \n", " demo.load(update_status, inputs=None, outputs=status_text)\n", " \n", " run_btn.click(\n", " run_action,\n", " inputs=None,\n", " outputs=[result_text, status_text]\n", " )\n", " \n", " gr.Markdown(\"---\")\n", " gr.Markdown(\"\"\"\n", " ### Rate Limits:\n", " - **Not logged in:** 3 clicks per minute (based on IP address)\n", " - **Logged in:** 30 clicks per minute (based on HF username)\n", " \n", " ### How it works:\n", " - Click the **Login** button to authenticate with Hugging Face\n", " - Click the **Run Action** button to test the rate limiting\n", " - The system tracks your clicks over a rolling 1-minute window\n", " \"\"\")\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
|
run.py
ADDED
@@ -0,0 +1,114 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
from datetime import datetime, timedelta
|
3 |
+
from collections import defaultdict
|
4 |
+
import threading
|
5 |
+
|
6 |
+
rate_limit_data = defaultdict(list)
|
7 |
+
lock = threading.Lock()
|
8 |
+
|
9 |
+
UNAUTH_RATE_LIMIT = 3
|
10 |
+
AUTH_RATE_LIMIT = 30
|
11 |
+
RATE_LIMIT_WINDOW = 60
|
12 |
+
|
13 |
+
def clean_old_entries(user_id):
|
14 |
+
"""Remove entries older than the rate limit window"""
|
15 |
+
current_time = datetime.now()
|
16 |
+
cutoff_time = current_time - timedelta(seconds=RATE_LIMIT_WINDOW)
|
17 |
+
rate_limit_data[user_id] = [
|
18 |
+
timestamp for timestamp in rate_limit_data[user_id]
|
19 |
+
if timestamp > cutoff_time
|
20 |
+
]
|
21 |
+
|
22 |
+
def get_user_identifier(profile: gr.OAuthProfile | None, request: gr.Request) -> tuple[str, bool]:
|
23 |
+
"""Get user identifier and whether they're authenticated"""
|
24 |
+
if profile is not None:
|
25 |
+
return profile.username, True
|
26 |
+
else:
|
27 |
+
if request:
|
28 |
+
return f"ip_{request.client.host}", False
|
29 |
+
return "ip_unknown", False
|
30 |
+
|
31 |
+
def check_rate_limit(user_id: str, is_authenticated: bool) -> tuple[bool, int, int]:
|
32 |
+
"""
|
33 |
+
Check if user has exceeded rate limit
|
34 |
+
Returns: (can_proceed, clicks_used, max_clicks)
|
35 |
+
"""
|
36 |
+
with lock:
|
37 |
+
clean_old_entries(user_id)
|
38 |
+
|
39 |
+
max_clicks = AUTH_RATE_LIMIT if is_authenticated else UNAUTH_RATE_LIMIT
|
40 |
+
clicks_used = len(rate_limit_data[user_id])
|
41 |
+
|
42 |
+
can_proceed = clicks_used < max_clicks
|
43 |
+
|
44 |
+
return can_proceed, clicks_used, max_clicks
|
45 |
+
|
46 |
+
def add_click(user_id: str):
|
47 |
+
"""Add a click timestamp for the user"""
|
48 |
+
with lock:
|
49 |
+
rate_limit_data[user_id].append(datetime.now())
|
50 |
+
|
51 |
+
def update_status(profile: gr.OAuthProfile | None, request: gr.Request) -> str:
|
52 |
+
"""Update the status message showing current rate limit info"""
|
53 |
+
user_id, is_authenticated = get_user_identifier(profile, request)
|
54 |
+
_, clicks_used, max_clicks = check_rate_limit(user_id, is_authenticated)
|
55 |
+
|
56 |
+
if is_authenticated:
|
57 |
+
return f"β
You are logged in as '{profile.username}'. You have clicked {clicks_used} times this minute. You have {max_clicks} total clicks per minute." # type: ignore
|
58 |
+
else:
|
59 |
+
return f"β οΈ You are not logged in. You have clicked {clicks_used} times this minute. You have {max_clicks} total clicks per minute."
|
60 |
+
|
61 |
+
def run_action(profile: gr.OAuthProfile | None, request: gr.Request) -> tuple[str, str]:
|
62 |
+
"""Handle the run button click with rate limiting"""
|
63 |
+
user_id, is_authenticated = get_user_identifier(profile, request)
|
64 |
+
can_proceed, clicks_used, max_clicks = check_rate_limit(user_id, is_authenticated)
|
65 |
+
|
66 |
+
if not can_proceed:
|
67 |
+
result = f"β Rate limit exceeded! You've used all {max_clicks} clicks for this minute. Please wait before trying again."
|
68 |
+
status = update_status(profile, request)
|
69 |
+
return result, status
|
70 |
+
|
71 |
+
add_click(user_id)
|
72 |
+
|
73 |
+
_, new_clicks_used, _ = check_rate_limit(user_id, is_authenticated)
|
74 |
+
|
75 |
+
result = f"β
Action executed successfully! (Click #{new_clicks_used})"
|
76 |
+
status = update_status(profile, request)
|
77 |
+
|
78 |
+
return result, status
|
79 |
+
|
80 |
+
with gr.Blocks(title="Rate Limiting Demo") as demo:
|
81 |
+
gr.Markdown("# Rate Limiting Demo App")
|
82 |
+
gr.Markdown("This app demonstrates rate limiting based on authentication status.")
|
83 |
+
|
84 |
+
gr.LoginButton()
|
85 |
+
|
86 |
+
status_text = gr.Markdown("Loading status...")
|
87 |
+
|
88 |
+
with gr.Row():
|
89 |
+
run_btn = gr.Button("π Run Action", variant="primary", scale=1)
|
90 |
+
|
91 |
+
result_text = gr.Markdown("")
|
92 |
+
|
93 |
+
demo.load(update_status, inputs=None, outputs=status_text)
|
94 |
+
|
95 |
+
run_btn.click(
|
96 |
+
run_action,
|
97 |
+
inputs=None,
|
98 |
+
outputs=[result_text, status_text]
|
99 |
+
)
|
100 |
+
|
101 |
+
gr.Markdown("---")
|
102 |
+
gr.Markdown("""
|
103 |
+
### Rate Limits:
|
104 |
+
- **Not logged in:** 3 clicks per minute (based on IP address)
|
105 |
+
- **Logged in:** 30 clicks per minute (based on HF username)
|
106 |
+
|
107 |
+
### How it works:
|
108 |
+
- Click the **Login** button to authenticate with Hugging Face
|
109 |
+
- Click the **Run Action** button to test the rate limiting
|
110 |
+
- The system tracks your clicks over a rolling 1-minute window
|
111 |
+
""")
|
112 |
+
|
113 |
+
if __name__ == "__main__":
|
114 |
+
demo.launch()
|