Metadata-Version: 2.4
Name: django-smart-ratelimit
Version: 0.2.0
Summary: A flexible and efficient rate limiting library for Django applications
Project-URL: Homepage, https://github.com/YasserShkeir/django-smart-ratelimit
Project-URL: Documentation, https://django-smart-ratelimit.readthedocs.io
Project-URL: Repository, https://github.com/YasserShkeir/django-smart-ratelimit
Project-URL: Issues, https://github.com/YasserShkeir/django-smart-ratelimit/issues
Project-URL: Changelog, https://github.com/YasserShkeir/django-smart-ratelimit/blob/main/CHANGELOG.md
Author-email: Yasser Shkeir <shkeiryasser@gmail.com>
License-Expression: MIT
License-File: LICENSE
Keywords: decorator,django,middleware,rate-limiting,redis
Classifier: Development Status :: 4 - Beta
Classifier: Framework :: Django
Classifier: Framework :: Django :: 3.2
Classifier: Framework :: Django :: 4.0
Classifier: Framework :: Django :: 4.1
Classifier: Framework :: Django :: 4.2
Classifier: Framework :: Django :: 5.0
Classifier: Framework :: Django :: 5.1
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Internet :: WWW/HTTP
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: System :: Systems Administration
Requires-Python: >=3.9
Requires-Dist: django>=3.2
Requires-Dist: redis>=4.0
Provides-Extra: dev
Requires-Dist: bandit>=1.7; extra == 'dev'
Requires-Dist: black>=22.0; extra == 'dev'
Requires-Dist: build>=0.8; extra == 'dev'
Requires-Dist: django-stubs>=4.0; extra == 'dev'
Requires-Dist: flake8-docstrings>=1.7; extra == 'dev'
Requires-Dist: flake8>=5.0; extra == 'dev'
Requires-Dist: isort>=5.0; extra == 'dev'
Requires-Dist: mypy>=1.0; extra == 'dev'
Requires-Dist: pre-commit>=2.20; extra == 'dev'
Requires-Dist: pytest-cov>=4.0; extra == 'dev'
Requires-Dist: pytest-django>=4.5; extra == 'dev'
Requires-Dist: pytest>=7.0; extra == 'dev'
Requires-Dist: safety>=2.0; extra == 'dev'
Requires-Dist: twine>=4.0; extra == 'dev'
Requires-Dist: types-redis>=4.0; extra == 'dev'
Description-Content-Type: text/markdown

# Django Smart Ratelimit

[![CI](https://github.com/YasserShkeir/django-smart-ratelimit/workflows/CI/badge.svg)](https://github.com/YasserShkeir/django-smart-ratelimit/actions)
[![PyPI version](https://img.shields.io/pypi/v/django-smart-ratelimit.svg)](https://pypi.org/project/django-smart-ratelimit/)
[![PyPI status](https://img.shields.io/pypi/status/django-smart-ratelimit.svg)](https://pypi.org/project/django-smart-ratelimit/)
[![Python versions](https://img.shields.io/pypi/pyversions/django-smart-ratelimit.svg)](https://pypi.org/project/django-smart-ratelimit/)
[![Django versions](https://img.shields.io/badge/Django-3.2%20%7C%204.0%20%7C%204.1%20%7C%204.2%20%7C%205.0%20%7C%205.1-blue.svg)](https://pypi.org/project/django-smart-ratelimit/)
[![Downloads](https://img.shields.io/pypi/dm/django-smart-ratelimit.svg)](https://pypi.org/project/django-smart-ratelimit/)
[![License](https://img.shields.io/pypi/l/django-smart-ratelimit.svg)](https://github.com/YasserShkeir/django-smart-ratelimit/blob/main/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 backend with extensible architecture
- 📊 **Rich Headers**: Standard rate limiting headers
- 🛡️ **Production Ready**: Comprehensive testing and error handling

## Quick Start

### Installation

```bash
pip install django-smart-ratelimit
```

### Basic Usage

#### Decorator Style

```python
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

```python
# 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

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

# Algorithm selection
RATELIMIT_USE_SLIDING_WINDOW = True  # or False for fixed window
```

#### Memory Backend

```python
# 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_USE_SLIDING_WINDOW = True  # or False for fixed window
```

## Usage Examples

### Decorator Examples

#### Basic Rate Limiting

```python
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

```python
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

```python
@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

```python
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

```python
# 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'`, `'memory'`) |
| `RATELIMIT_REDIS`                    | `dict` | `{}`           | Redis configuration                 |
| `RATELIMIT_MEMORY_MAX_KEYS`          | `int`  | `10000`        | Maximum keys for memory backend     |
| `RATELIMIT_MEMORY_CLEANUP_INTERVAL`  | `int`  | `300`          | Cleanup interval (seconds)          |
| `RATELIMIT_USE_SLIDING_WINDOW`       | `bool` | `True`         | Use sliding window algorithm        |
| `RATELIMIT_KEY_PREFIX`               | `str`  | `'ratelimit:'` | Redis key prefix                    |

## Development

### Running Tests

```bash
# 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

```bash
# Format code
black django_smart_ratelimit tests

# Check linting
flake8 django_smart_ratelimit tests

# Type checking
mypy django_smart_ratelimit
```

### Pre-commit Hooks

```bash
# 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](LICENSE) file for details.

## Changelog

### v0.1.0 (Initial Release)

- Basic decorator and middleware support
- Redis backend with sliding window algorithm
- Comprehensive test suite
- Documentation and examples

## Support

- 📖 [Documentation](docs/design.md)
- 🐛 [Issue Tracker](https://github.com/YasserShkeir/django-smart-ratelimit/issues)
- 💬 [Discussions](https://github.com/YasserShkeir/django-smart-ratelimit/discussions)

## 💖 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
