Throttle every endpoint: SlowAPIMiddleware + tight cap on /api/exports#309
Merged
Conversation
slowapi's `default_limits` was a no-op without `SlowAPIMiddleware`
— only routes with an explicit `@limiter.limit(...)` decorator got
throttled. That left ~70 of ~85 endpoints (every entity GET route,
exports, news, mechanics pages, the new admin sketches) with zero
rate limiting. A scraper could hammer `/api/cards` or
`/api/exports/{lang}` until they ran out of bandwidth budget.
Adds `SlowAPIMiddleware` so the limiter's 300/min default applies
to every request. Routes that already have explicit decorators
(submit_run 3000/hr, list/leaderboard 120/min, shared 60/min, etc.)
keep their tighter limits — slowapi uses the most restrictive
applicable limit per request, so adding the middleware is purely
additive: nothing currently throttled gets looser.
Tightened `/api/exports/{lang}` from the new 300/min floor to
10/hour because each request builds a multi-file zip with deflate
compression on 15+ JSON files (1-3 MB output, 20-100ms CPU). A
legitimate "give me a snapshot of the eng locale" call is rare —
10/hour leaves enough headroom for "I'm trying all 14 languages"
and still slams the door on scrapers.
Smoke-tested locally: 350 sequential `/api/cards` requests from one
IP cleanly returned exactly 300 × 200 followed by 50 × 429.
After deploy, every endpoint is throttled at 300/min default. The
upcoming admin rate-limit dial (PR #308) lets you tune that on the
fly per slug without redeploying — but the floor is in place now.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
slowapi'sdefault_limits=["300/minute"]setting on the mainLimiterwas a no-op withoutSlowAPIMiddleware— only routes carrying an explicit@limiter.limit(...)decorator got throttled. The audit:So
/api/cards,/api/relics,/api/exports/{lang}, etc. had zero rate limit. A scraper could hammer them as fast as the box could serve until they ran out of bandwidth.Changes
SlowAPIMiddleware— applies the limiter'sdefault_limitsto every request before the route runs. slowapi picks the most restrictive applicable limit per request, so routes with their own decorator keep their tighter limit unchanged./api/exports/{lang}from the new 300/min floor to 10/hour — each request builds a 15-file ZIP with deflate compression (1-3 MB / 20-100ms CPU). Cheap legitimate use, expensive abuse. 10/hour covers "snapshot all 14 locales" with room to spare; anything more is scraping.Smoke test
Exactly the expected split. Middleware works.
After deploy
Every endpoint has a floor of 300/min/IP. Routes with their own
@limiter.limit(...)keep their tighter override. The upcoming admin rate-limit dial (PR #308) lets you tune any slug on the fly without redeploying — but the floor is in place now.