A Python rate limiter library for FastAPI and Flask applications
Project description
Rate Limiter
A Python rate limiter library for FastAPI and Flask applications. This library provides a simple, thread-safe rate limiting implementation using a sliding window algorithm.
Features
- 🚀 Easy to use - Simple API for both FastAPI and Flask
- 🔒 Thread-safe - Safe for concurrent requests
- ⚡ Lightweight - No external dependencies for core functionality
- 🎯 Flexible - Support for custom key functions and exempt paths
- 📊 Headers - Automatic rate limit headers in responses
Installation
Current Status: This package is not yet published to PyPI. Use one of the installation methods below.
Option 1: Install from Local Source (Development/Use)
If you have the source code locally:
# Install in development mode (editable)
pip install -e .
# Or install normally
pip install .
For framework-specific integrations, install the dependencies:
# FastAPI
pip install -e ".[fastapi]"
# or
pip install fastapi
# Flask
pip install -e ".[flask]"
# or
pip install flask
# Both
pip install -e ".[all]"
Option 2: Install from Git Repository
pip install git+https://github.com/yourusername/python-rate-limiter.git
Option 3: Publish to PyPI (For Public Distribution)
Note: The package name python-rate-limiter may already be taken on PyPI. Check availability first and consider alternative names if needed.
To make the package available via pip install python-rate-limiter, you need to publish it to PyPI:
-
Create accounts:
-
Build the package:
pip install build twine python -m build
-
Test on TestPyPI:
python -m twine upload --repository testpypi dist/*
-
Publish to PyPI:
python -m twine upload dist/*
-
Update setup.py:
- Update the
urlfield with your actual repository URL - Update
authorandauthor_emailwith your information - If the package name is taken, update the
namefield
- Update the
After publishing, users can install with:
pip install python-rate-limiter
For detailed publishing instructions, see PUBLISHING.md.
Quick Start
FastAPI
Using Middleware (Recommended)
from fastapi import FastAPI
from python_rate_limiter import FastAPIRateLimiter
app = FastAPI()
# Initialize rate limiter
limiter = FastAPIRateLimiter(
max_requests=100,
time_window=60.0, # 60 seconds
exempt_paths=["/health", "/docs"] # Optional: exempt certain paths
)
# Add middleware
app.middleware("http")(limiter.middleware)
@app.get("/")
async def root():
return {"message": "Hello World"}
@app.get("/api/data")
async def get_data():
return {"data": "some data"}
Using Decorator
from fastapi import FastAPI, Request
from python_rate_limiter import rate_limit
app = FastAPI()
@app.get("/api/endpoint")
@rate_limit(max_requests=10, time_window=60)
async def endpoint(request: Request):
return {"message": "Hello"}
Custom Key Function
from fastapi import FastAPI, Request
from python_rate_limiter import rate_limit
app = FastAPI()
def get_user_id(request: Request) -> str:
# Extract user ID from request (e.g., from JWT token)
return request.headers.get("X-User-ID", "anonymous")
@app.get("/api/user-data")
@rate_limit(max_requests=50, time_window=60, key_func=get_user_id)
async def user_data(request: Request):
return {"user_data": "..."}
Flask
Using Extension (Recommended)
from flask import Flask
from python_rate_limiter import FlaskRateLimiter
app = Flask(__name__)
# Initialize rate limiter
limiter = FlaskRateLimiter(
max_requests=100,
time_window=60.0,
exempt_paths=["/health", "/static"] # Optional: exempt certain paths
)
# Initialize with app
limiter.init_app(app)
@app.route("/")
def root():
return {"message": "Hello World"}
@app.route("/api/data")
def get_data():
return {"data": "some data"}
Using Decorator
from flask import Flask
from python_rate_limiter import rate_limit
app = Flask(__name__)
@app.route("/api/endpoint")
@rate_limit(max_requests=10, time_window=60)
def endpoint():
return {"message": "Hello"}
Custom Key Function
from flask import Flask, request
from python_rate_limiter import rate_limit
app = Flask(__name__)
def get_user_id() -> str:
# Extract user ID from request (e.g., from session or JWT)
return request.headers.get("X-User-ID", "anonymous")
@app.route("/api/user-data")
@rate_limit(max_requests=50, time_window=60, key_func=get_user_id)
def user_data():
return {"user_data": "..."}
Core API
RateLimiter
The core rate limiter class can be used independently:
from python_rate_limiter import RateLimiter
limiter = RateLimiter(max_requests=100, time_window=60.0)
# Check if request is allowed
is_allowed, retry_after = limiter.is_allowed("user_ip_address")
if not is_allowed:
print(f"Rate limit exceeded. Retry after {retry_after} seconds")
# Or raise exception
try:
limiter.check_rate_limit("user_ip_address")
except RateLimitExceeded as e:
print(f"Rate limit exceeded. Retry after {e.retry_after} seconds")
# Get remaining requests
remaining = limiter.get_remaining("user_ip_address")
# Reset rate limit
limiter.reset("user_ip_address") # Reset specific key
limiter.reset() # Reset all keys
Response Headers
The library automatically adds rate limit headers to responses:
X-RateLimit-Limit: Maximum number of requests allowedX-RateLimit-Remaining: Number of remaining requestsX-RateLimit-Reset: Unix timestamp when the rate limit resetsRetry-After: Seconds to wait before retrying (when rate limit exceeded)
Error Responses
When rate limit is exceeded, the library returns:
- Status Code:
429 Too Many Requests - Response Body:
{ "error": "Rate limit exceeded", "retry_after": 45.2, "message": "Too many requests. Please try again later." }
Configuration Options
FastAPIRateLimiter / FlaskRateLimiter
max_requests(int): Maximum number of requests allowed (default: 100)time_window(float): Time window in seconds (default: 60.0)key_func(Callable): Function to extract key from request (default: uses IP address)exempt_paths(list[str]): List of path patterns to exempt from rate limiting
Rate Limiter Algorithm
The library uses a sliding window algorithm, which provides accurate rate limiting by tracking individual request timestamps within the time window.
Examples
See the examples/ directory for complete working examples.
License
MIT License
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file python_rate_limiter-0.1.0.tar.gz.
File metadata
- Download URL: python_rate_limiter-0.1.0.tar.gz
- Upload date:
- Size: 9.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0b72fe176d3b9764b70ce22973181afe474be3f6323f2d56e6c8aa262eaf7073
|
|
| MD5 |
5e6c3b509307185e1a69c9e30f2521b9
|
|
| BLAKE2b-256 |
1ec942959dba6688a8788c6d1c24a43ec176f9b8b5297aecd4e9b3ebedfe4e09
|
File details
Details for the file python_rate_limiter-0.1.0-py3-none-any.whl.
File metadata
- Download URL: python_rate_limiter-0.1.0-py3-none-any.whl
- Upload date:
- Size: 9.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8e01ff99c57f12368c84f8f381bba7b09a4a14e6ef1df0707e7f0365b2693b9a
|
|
| MD5 |
6a17711f4379884e379813440dce272d
|
|
| BLAKE2b-256 |
c33486c2e4024f618a95907bbb3cf39773cd7d457e51f9e4088a9081b5c7c87d
|