Update docs to be more readable and add uv instructions
Rewrote README and DEVELOPMENT.md to sound less robotic. Added changelog documenting the new test suite and other recent changes.
This commit is contained in:
42
CHANGELOG.md
Normal file
42
CHANGELOG.md
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
All notable changes to fastapi-traffic will be documented here.
|
||||||
|
|
||||||
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
||||||
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## [Unreleased]
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- `get_stats()` method to `MemoryBackend` for consistency with `RedisBackend`
|
||||||
|
- Comprehensive test suite with 134 tests covering:
|
||||||
|
- All five rate limiting algorithms with timing and concurrency tests
|
||||||
|
- Backend tests for Memory and SQLite with edge cases
|
||||||
|
- Decorator and middleware integration tests
|
||||||
|
- Exception handling and configuration validation
|
||||||
|
- End-to-end integration tests with FastAPI apps
|
||||||
|
- `httpx` and `pytest-asyncio` as dev dependencies for testing
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Improved documentation in README.md and DEVELOPMENT.md
|
||||||
|
- Added `asyncio_default_fixture_loop_scope` config for pytest-asyncio compatibility
|
||||||
|
|
||||||
|
## [0.1.0] - 2025-01-09
|
||||||
|
|
||||||
|
Initial release.
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- Core rate limiting with `@rate_limit` decorator
|
||||||
|
- Five algorithms: Token Bucket, Sliding Window, Fixed Window, Leaky Bucket, Sliding Window Counter
|
||||||
|
- Three storage backends: Memory (default), SQLite (persistent), Redis (distributed)
|
||||||
|
- Middleware support for global rate limiting via `RateLimitMiddleware`
|
||||||
|
- Dependency injection support with `RateLimitDependency`
|
||||||
|
- Custom key extractors for flexible rate limit grouping (by IP, API key, user, etc.)
|
||||||
|
- Configurable exemptions with `exempt_when` callback
|
||||||
|
- Rate limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)
|
||||||
|
- `RateLimitExceeded` exception with `retry_after` and `limit_info`
|
||||||
|
- Full async support throughout
|
||||||
|
- Strict type hints (pyright/mypy compatible)
|
||||||
|
- Redis backend with Lua scripts for atomic operations
|
||||||
|
- SQLite backend with WAL mode and connection pooling
|
||||||
|
- Memory backend with LRU eviction and TTL cleanup
|
||||||
152
DEVELOPMENT.md
Normal file
152
DEVELOPMENT.md
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
# Development Guide
|
||||||
|
|
||||||
|
Want to contribute or just poke around? Here's how to get set up.
|
||||||
|
|
||||||
|
## What you'll need
|
||||||
|
|
||||||
|
- Python 3.10 or newer
|
||||||
|
- [uv](https://github.com/astral-sh/uv) (recommended) or pip
|
||||||
|
- Docker if you want to test the Redis backend
|
||||||
|
|
||||||
|
## Getting started
|
||||||
|
|
||||||
|
### Using uv (the fast way)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone https://gitlab.com/bereckobrian/fastapi-traffic.git
|
||||||
|
cd fastapi-traffic
|
||||||
|
|
||||||
|
# This creates a venv and installs everything
|
||||||
|
uv sync
|
||||||
|
```
|
||||||
|
|
||||||
|
That's it. uv figures out the rest.
|
||||||
|
|
||||||
|
### Using pip
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone https://gitlab.com/bereckobrian/fastapi-traffic.git
|
||||||
|
cd fastapi-traffic
|
||||||
|
|
||||||
|
python -m venv .venv
|
||||||
|
source .venv/bin/activate # Windows: .venv\Scripts\activate
|
||||||
|
|
||||||
|
pip install -e ".[dev]"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Redis for testing (optional)
|
||||||
|
|
||||||
|
If you want to run the Redis backend tests:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker run -d -p 6379:6379 redis:alpine
|
||||||
|
```
|
||||||
|
|
||||||
|
## Running tests
|
||||||
|
|
||||||
|
We have 134 tests covering algorithms, backends, decorators, middleware, and integration scenarios.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Run everything
|
||||||
|
uv run pytest
|
||||||
|
|
||||||
|
# Or with pip
|
||||||
|
pytest
|
||||||
|
|
||||||
|
# With coverage report
|
||||||
|
pytest --cov=fastapi_traffic
|
||||||
|
|
||||||
|
# Just one file
|
||||||
|
pytest tests/test_algorithms.py
|
||||||
|
|
||||||
|
# Match a pattern
|
||||||
|
pytest -k "token_bucket"
|
||||||
|
```
|
||||||
|
|
||||||
|
Tests run async by default via pytest-asyncio.
|
||||||
|
|
||||||
|
## Type checking
|
||||||
|
|
||||||
|
We use pyright in strict mode:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
uv run pyright
|
||||||
|
# or just: pyright
|
||||||
|
```
|
||||||
|
|
||||||
|
VS Code with Pylance gives you real-time feedback.
|
||||||
|
|
||||||
|
## Linting
|
||||||
|
|
||||||
|
Ruff handles both linting and formatting:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check for issues
|
||||||
|
uv run ruff check .
|
||||||
|
|
||||||
|
# Auto-fix
|
||||||
|
uv run ruff check . --fix
|
||||||
|
|
||||||
|
# Format
|
||||||
|
uv run ruff format .
|
||||||
|
```
|
||||||
|
|
||||||
|
## Running examples
|
||||||
|
|
||||||
|
The `examples/` folder has working examples you can run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Basic usage
|
||||||
|
uv run python examples/01_quickstart.py
|
||||||
|
|
||||||
|
# Redis example (needs Redis running)
|
||||||
|
REDIS_URL=redis://localhost:6379/0 uv run python examples/07_redis_distributed.py
|
||||||
|
```
|
||||||
|
|
||||||
|
Then open `http://localhost:8000` in your browser.
|
||||||
|
|
||||||
|
## Project layout
|
||||||
|
|
||||||
|
```
|
||||||
|
fastapi_traffic/
|
||||||
|
├── __init__.py # Public exports
|
||||||
|
├── exceptions.py # Custom exceptions
|
||||||
|
├── middleware.py # ASGI middleware
|
||||||
|
├── backends/
|
||||||
|
│ ├── base.py # Backend interface
|
||||||
|
│ ├── memory.py # In-memory (default)
|
||||||
|
│ ├── sqlite.py # SQLite
|
||||||
|
│ └── redis.py # Redis
|
||||||
|
└── core/
|
||||||
|
├── algorithms.py # Rate limiting algorithms
|
||||||
|
├── config.py # Configuration
|
||||||
|
├── decorator.py # @rate_limit decorator
|
||||||
|
└── limiter.py # RateLimiter class
|
||||||
|
```
|
||||||
|
|
||||||
|
## Adding a backend
|
||||||
|
|
||||||
|
1. Create a file in `fastapi_traffic/backends/`
|
||||||
|
2. Subclass `Backend` from `base.py`
|
||||||
|
3. Implement: `get`, `set`, `delete`, `exists`, `increment`, `clear`
|
||||||
|
4. Optionally: `ping`, `get_stats`, `close`
|
||||||
|
5. Add tests in `tests/test_backends.py`
|
||||||
|
6. Export from `__init__.py` if public
|
||||||
|
|
||||||
|
## Adding an algorithm
|
||||||
|
|
||||||
|
1. Add enum value to `Algorithm` in `core/algorithms.py`
|
||||||
|
2. Create a handler class
|
||||||
|
3. Register it in the dispatcher
|
||||||
|
4. Add tests in `tests/test_algorithms.py`
|
||||||
|
5. Document in README
|
||||||
|
|
||||||
|
## Tips
|
||||||
|
|
||||||
|
- Memory backend is great for development - no dependencies
|
||||||
|
- Use `skip_on_error=True` if you don't want backend errors blocking requests
|
||||||
|
- Check examples for real usage patterns
|
||||||
|
|
||||||
|
## Questions?
|
||||||
|
|
||||||
|
Open an issue. Happy to help.
|
||||||
49
README.md
49
README.md
@@ -1,20 +1,21 @@
|
|||||||
# FastAPI Traffic
|
# FastAPI Traffic
|
||||||
|
|
||||||
Production-grade rate limiting for FastAPI with multiple algorithms and storage backends.
|
A rate limiting library for FastAPI that actually works in production. Pick your algorithm, pick your backend, and you're good to go.
|
||||||
|
|
||||||
## Features
|
## Why this library?
|
||||||
|
|
||||||
- **Multiple Algorithms**: Token Bucket, Sliding Window, Fixed Window, Leaky Bucket, Sliding Window Counter
|
Most rate limiting solutions are either too simple (fixed window only) or too complex (requires a PhD to configure). This one tries to hit the sweet spot:
|
||||||
- **Multiple Backends**: In-memory (default), SQLite (persistent), Redis (distributed)
|
|
||||||
- **Decorator-based**: Simple `@rate_limit` decorator for endpoints
|
- **Five algorithms** to choose from, depending on your use case
|
||||||
- **Middleware Support**: Global rate limiting via middleware
|
- **Three storage backends**: memory for development, SQLite for single-node, Redis for distributed
|
||||||
- **Dependency Injection**: Use as FastAPI dependency for more control
|
- **Works how you'd expect**: decorator for endpoints, middleware for global limits
|
||||||
- **Strict Typing**: Full type hints, pyright/mypy compatible
|
- **Fully async** and type-checked with pyright
|
||||||
- **Customizable**: Custom key extractors, exemptions, callbacks
|
- **Sensible defaults** but configurable when you need it
|
||||||
- **Production Ready**: Connection pooling, async support, proper error handling
|
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
|
### Using pip
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Basic installation (memory backend only)
|
# Basic installation (memory backend only)
|
||||||
pip install fastapi-traffic
|
pip install fastapi-traffic
|
||||||
@@ -26,6 +27,19 @@ pip install fastapi-traffic[redis]
|
|||||||
pip install fastapi-traffic[all]
|
pip install fastapi-traffic[all]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Using uv
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Basic installation
|
||||||
|
uv add fastapi-traffic
|
||||||
|
|
||||||
|
# With Redis support
|
||||||
|
uv add fastapi-traffic[redis]
|
||||||
|
|
||||||
|
# With all extras
|
||||||
|
uv add fastapi-traffic[all]
|
||||||
|
```
|
||||||
|
|
||||||
## Quick Start
|
## Quick Start
|
||||||
|
|
||||||
### Basic Usage with Decorator
|
### Basic Usage with Decorator
|
||||||
@@ -219,20 +233,7 @@ When `include_headers=True`, responses include:
|
|||||||
|
|
||||||
## Development
|
## Development
|
||||||
|
|
||||||
```bash
|
See [DEVELOPMENT.md](DEVELOPMENT.md) for setting up a development environment and contributing.
|
||||||
# Install dev dependencies
|
|
||||||
pip install -e ".[dev]"
|
|
||||||
|
|
||||||
# Run tests
|
|
||||||
pytest
|
|
||||||
|
|
||||||
# Type checking
|
|
||||||
pyright
|
|
||||||
|
|
||||||
# Linting
|
|
||||||
ruff check .
|
|
||||||
ruff format .
|
|
||||||
```
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user