Skip to main content

A flexible and efficient rate limiting library for Django applications

Project description

Django Smart Ratelimit

CI PyPI version PyPI status Python versions Django versions Downloads License

A flexible and efficient rate limiting library for Django applications with support for multiple backends and sliding window algorithms.

Features

  • 🚀 High Performance: Atomic operations using Redis Lua scripts
  • 🔧 Flexible Configuration: Both decorator and middleware support
  • 🪟 Multiple Algorithms: Fixed window and sliding window rate limiting
  • 🔌 Multiple Backends: Redis, Database, and Memory backends with extensible architecture
  • 📊 Rich Headers: Standard rate limiting headers
  • 🛡️ Production Ready: Comprehensive testing and error handling

Quick Start

Installation

pip install django-smart-ratelimit

Basic Usage

Decorator Style

from django_smart_ratelimit import rate_limit

@rate_limit(key='ip', rate='10/m')
def my_view(request):
    return HttpResponse('Hello World')

@rate_limit(key='user:{user.id}', rate='100/h', block=True)
def api_endpoint(request):
    return JsonResponse({'data': 'some data'})

Middleware Style

# settings.py
MIDDLEWARE = [
    'django_smart_ratelimit.middleware.RateLimitMiddleware',
    # ... other middleware
]

RATELIMIT_MIDDLEWARE = {
    'DEFAULT_RATE': '100/m',
    'BACKEND': 'redis',
    'SKIP_PATHS': ['/admin/', '/health/'],
    'RATE_LIMITS': {
        '/api/': '1000/h',
        '/auth/login/': '5/m',
    }
}

Configuration

Redis Backend

# settings.py
RATELIMIT_BACKEND = 'redis'
RATELIMIT_REDIS = {
    'host': 'localhost',
    'port': 6379,
    'db': 0,
    'password': None,
}

# Algorithm selection
RATELIMIT_ALGORITHM = 'sliding_window'  # or 'fixed_window'

Memory Backend

# settings.py
RATELIMIT_BACKEND = 'memory'

# Memory backend configuration
RATELIMIT_MEMORY_MAX_KEYS = 10000  # Maximum number of keys to store
RATELIMIT_MEMORY_CLEANUP_INTERVAL = 300  # Cleanup interval in seconds

# Algorithm selection
RATELIMIT_ALGORITHM = "sliding_window"  # or "fixed_window"

Database Backend

# settings.py
RATELIMIT_BACKEND = 'database'

# Database backend configuration
RATELIMIT_DATABASE_CLEANUP_THRESHOLD = 1000  # Cleanup threshold for entries

# Algorithm selection
RATELIMIT_ALGORITHM = "sliding_window"  # or "fixed_window"

Usage Examples

Decorator Examples

Basic Rate Limiting

from django_smart_ratelimit import rate_limit

# Limit by IP address
@rate_limit(key='ip', rate='10/m')
def public_api(request):
    return JsonResponse({'message': 'Hello World'})

# Limit by user
@rate_limit(key='user', rate='100/h')
def user_api(request):
    return JsonResponse({'user_data': '...'})

Custom Key Functions

def custom_key(request):
    if request.user.is_authenticated:
        return f"user:{request.user.id}"
    return f"ip:{request.META.get('REMOTE_ADDR')}"

@rate_limit(key=custom_key, rate='50/m')
def smart_api(request):
    return JsonResponse({'data': '...'})

Non-blocking Rate Limiting

@rate_limit(key='ip', rate='10/m', block=False)
def api_with_headers(request):
    # This will add headers but not block requests
    return JsonResponse({'data': '...'})

Middleware Examples

Path-based Rate Limiting

RATELIMIT_MIDDLEWARE = {
    'DEFAULT_RATE': '100/m',
    'RATE_LIMITS': {
        '/api/public/': '1000/h',
        '/api/private/': '100/h',
        '/auth/': '5/m',
        '/upload/': '10/h',
    }
}

Custom Key Functions

# utils.py
def user_key_function(request):
    if request.user.is_authenticated:
        return f"user:{request.user.id}"
    return f"ip:{request.META.get('REMOTE_ADDR')}"

def api_key_function(request):
    api_key = request.META.get('HTTP_X_API_KEY')
    if api_key:
        return f"api_key:{api_key}"
    return f"ip:{request.META.get('REMOTE_ADDR')}"

# settings.py
RATELIMIT_MIDDLEWARE = {
    'KEY_FUNCTION': 'myapp.utils.user_key_function',
    'RATE_LIMITS': {
        '/api/': '1000/h',
    }
}

Rate Formats

The library supports several rate formats:

  • 10/s - 10 requests per second
  • 100/m - 100 requests per minute
  • 1000/h - 1000 requests per hour
  • 10000/d - 10000 requests per day

Response Headers

When rate limiting is applied, the following headers are added:

X-RateLimit-Limit: 100
X-RateLimit-Remaining: 75
X-RateLimit-Reset: 1640995200

Algorithms

Fixed Window

Simple and memory-efficient algorithm that resets the counter at fixed intervals.

Pros:

  • Low memory usage
  • Simple implementation
  • Predictable reset times

Cons:

  • Potential for burst traffic
  • Less accurate limiting

Sliding Window

More accurate algorithm that maintains a sliding window of requests.

Pros:

  • Accurate rate limiting
  • No burst traffic issues
  • Smooth rate limiting

Cons:

  • Higher memory usage
  • More complex implementation

Configuration Reference

Decorator Parameters

Parameter Type Default Description
key str or callable Required Rate limit key or key function
rate str Required Rate limit (e.g., '10/m')
block bool True Block requests when limit exceeded
backend str None Backend to use (uses default if None)

Middleware Settings

Setting Type Default Description
DEFAULT_RATE str '100/m' Default rate limit
BACKEND str 'redis' Backend to use
KEY_FUNCTION str None Import path to key function
BLOCK bool True Block requests when limit exceeded
SKIP_PATHS list [] Paths to skip rate limiting
RATE_LIMITS dict {} Path-specific rate limits

Backend Settings

Setting Type Default Description
RATELIMIT_BACKEND str 'redis' Backend to use ('redis', 'database', 'memory')
RATELIMIT_ALGORITHM str 'sliding_window' Algorithm to use ('sliding_window', 'fixed_window')
RATELIMIT_REDIS dict {} Redis configuration
RATELIMIT_DATABASE_CLEANUP_THRESHOLD int 1000 Cleanup threshold for database backend
RATELIMIT_MEMORY_MAX_KEYS int 10000 Maximum keys for memory backend
RATELIMIT_MEMORY_CLEANUP_INTERVAL int 300 Cleanup interval (seconds)
RATELIMIT_KEY_PREFIX str 'ratelimit:' Redis key prefix

Development

Running Tests

# Install development dependencies
pip install -e .[dev]

# Run tests
pytest

# Run tests with coverage
pytest --cov=django_smart_ratelimit --cov-report=html

# Run specific test file
pytest tests/test_decorator.py

Code Quality

# Format code
black django_smart_ratelimit tests

# Check linting
flake8 django_smart_ratelimit tests

# Type checking
mypy django_smart_ratelimit

Pre-commit Hooks

# Install pre-commit hooks
pre-commit install

# Run hooks manually
pre-commit run --all-files

Contributing

We welcome contributions! Please follow these steps:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Make your changes
  4. Add tests for your changes
  5. Run the test suite (pytest)
  6. Commit your changes (git commit -m 'Add amazing feature')
  7. Push to the branch (git push origin feature/amazing-feature)
  8. Open a Pull Request

Contribution Guidelines

  • Write tests for new features
  • Follow the existing code style
  • Add docstrings to new functions and classes
  • Update documentation as needed
  • Add type hints where appropriate

License

This project is licensed under the MIT License - see the LICENSE file for details.

Changelog

See CHANGELOG.md for detailed version history and release notes.

Support

💖 Support the Project

If this library has saved you time and effort, consider supporting its development:

Cryptocurrency Donations

  • USDT (Ethereum): 0x202943b3a6CC168F92871d9e295537E6cbc53Ff4

Alternative Support Methods

  • Star this repository on GitHub
  • 🐛 Report bugs and suggest features
  • 🔀 Contribute code improvements
  • 📢 Share with your team and community

Your support helps maintain and improve this open-source project! 🙏

Acknowledgments

  • Created by Yasser Shkeir
  • Inspired by existing Django rate limiting libraries
  • Thanks to the Django and Redis communities
  • Special thanks to all contributors

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

django_smart_ratelimit-0.3.0.tar.gz (38.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

django_smart_ratelimit-0.3.0-py3-none-any.whl (25.6 kB view details)

Uploaded Python 3

File details

Details for the file django_smart_ratelimit-0.3.0.tar.gz.

File metadata

  • Download URL: django_smart_ratelimit-0.3.0.tar.gz
  • Upload date:
  • Size: 38.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for django_smart_ratelimit-0.3.0.tar.gz
Algorithm Hash digest
SHA256 df1ee1657804564ae8a411b0b95caaf56353ec60e1286aeab3fde4e1f460a5d4
MD5 925e4531905d385288adb12e88769b5a
BLAKE2b-256 884580bf7fd49eeff4a3edb0579d6ef499f869fde84a2b69d83512835893f3b7

See more details on using hashes here.

File details

Details for the file django_smart_ratelimit-0.3.0-py3-none-any.whl.

File metadata

File hashes

Hashes for django_smart_ratelimit-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 15614b4291751255e18b7fd77019468bf1ee1dd880e406e3e1f57de3c3a24448
MD5 fb0b6b14c2b798f7fa1dd317d4d8e2a3
BLAKE2b-256 893abe35ab3bb4e6102556b3d47297cb52911a6cc7b8cc546944bef593e49aa6

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page