jetio-ratelimit
Rate limiting for Jetio: sliding-window
by default, IP- or account-keyed (or both, stacked), usable as middleware
for routes you don't own the handler for (like jetio-auth's /login) and
as a Depends()-composable dependency for routes you do (a CrudRouter
policy, a hand-written route).
- docs/USAGE.md -- the full guide: every mode, every key function, stacking/reusing policies, handling a 429, testing your integration, troubleshooting. Start here for "how do I do X."
- DESIGN.md -- the reasoning: why sliding window over token bucket, why IP-only limiting is weak against real credential stuffing, and the real bugs found in Jetio/jetio-auth along the way. Start here for "why does it work this way."
Install
pip install -e .[dev] # from this directory, for now -- not yet published
Quickstart
from jetio import Jetio, CrudRouter
from jetio_auth import AuthRouter
from jetio_ratelimit import RateLimiter, InMemoryStore, Limit, by_ip, by_field, by_user
app = Jetio()
auth = AuthRouter(User, company_name="My App")
auth.register_routes(app) # POST /register, POST /login
limiter = RateLimiter(store=InMemoryStore())
# Middleware mode: protects /login, which AuthRouter registers internally --
# there's no Depends() hook to attach to on a route we don't define.
# protect_many() stacks two independent limits in one call; either tripping
# blocks the request. AUTH_POLICY is a plain list, so the same two rules
# can be applied to /register or any other auth-adjacent route with one
# more protect_many() call each -- see "Reusing a policy across routes" below.
AUTH_POLICY = [
Limit(max_attempts=5, window_seconds=60, key_func=by_ip),
Limit(max_attempts=3, window_seconds=60, key_func=by_field("username")),
]
limiter.protect_many(app, path="/login", limits=AUTH_POLICY)
# Dependency mode: composes into a CrudRouter policy, keyed by the
# authenticated user rather than IP.
CrudRouter(
model=Order,
secure=True,
policy={
"POST": limiter.dependency(
max_attempts=10, window_seconds=60,
key_func=by_user, identity_dependency=auth.get_auth_dependency(),
),
},
).register_routes(app)
Run examples/demo_app.py and hit it with curl to see
both modes working against a real jetio-auth-backed app. For why /login
gets two stacked limits instead of one, how to reuse one policy across many
routes, by_header-keyed API endpoints, using dependency mode outside
CrudRouter, and more, see docs/USAGE.md.
Status
v0.1: sliding window algorithm, in-memory store, both API modes, IP/account/
header/user keying, protect_many() for stacking multiple limits (or
reusing one policy across many routes) in one call. Not yet done: Redis store (for
anything running more than one worker -- InMemoryStore's state is
per-process), progressive lockout on repeat violations, an equivalent
stacking helper for dependency mode, PyPI publish. See DESIGN.md's build
order.
Known limitations
- InMemoryStore is single-process. Behind multiple workers/replicas,
each one has its own counters, so the effective limit becomes
limit * worker_count. Don't treat this as sufficient for a horizontally-scaled deployment yet. - No
X-Forwarded-Forsupport. Behind a reverse proxy,by_ipsees the proxy's IP, not the real client's. Not yet configurable.
Release files for jetio-ratelimit 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| jetio_ratelimit-0.1.0.tar.gz | 17.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| jetio_ratelimit-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 32.0 kB
Release files / jetio_ratelimit-0.1.0.tar.gz
| Download URL | jetio_ratelimit-0.1.0.tar.gz |
|---|---|
| Size | 17.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
7ec29225c009328e00a0da660361f00102df9641ab83bfc844896a40011888be
|
|
BLAKE2b-256 checksum How to use checksums |
a9982eb09de59d1490a8a2da6f5c17c63bc65af802111afa120aacc27a179208
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.10
|
Release files / jetio_ratelimit-0.1.0-py3-none-any.whl
| Download URL | jetio_ratelimit-0.1.0-py3-none-any.whl |
|---|---|
| Size | 14.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
b50ad96ce09d42b54fba2ea42332f74bbf15e7e7405cea87fce3602c9ac1b785
|
|
BLAKE2b-256 checksum How to use checksums |
1468e4b2a9470d80282dc6fff075f9f276d6f5aaf48fa4d3b7a6b55d30cc7fd1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.10
|