Rate limiting is useful for certain public API endpoints. Examples are:
Login endpoints - reducing the speed with which passwords can be brute forced.
Computationally intensive endpoints, which could lead to a DOS attack.
Usage is simple - just wrap your ASGI app:
from piccolo_api.rate_limiting.middleware import RateLimitingMiddleware app = RateLimitingMiddleware(my_asgi_app)
- class piccolo_api.rate_limiting.middleware.RateLimitingMiddleware(app: ASGIApp, provider: Optional[RateLimitProvider] = None)[source]¶
Blocks clients who exceed a given number of requests in a given time period.
app – The ASGI app to wrap.
provider – Provides the logic around rate limiting. If not specified, it will default to a
The middleware can work with different Providers, which are responsible for storing traffic data, and signalling when a rate limit has been exceeded.
InMemoryLimitProvider is used.
Stores the traffic data in memory. You can customise it as follows:
app = RateLimitingMiddleware( my_asgi_app, provider=InMemoryLimitProvider( limit=1000, timespan=300 ), )
limit is the number of requests needed by a client within the
timespan (measured in seconds) to trigger a 429 error (too many requests).
If you want a blocked client to be allowed access again after a time period,
specify this using the
app = RateLimitingMiddleware( my_asgi_app, provider=InMemoryLimitProvider( limit=1000, timespan=300, block_duration=300 # Blocked for 5 minutes ), )
- class piccolo_api.rate_limiting.middleware.InMemoryLimitProvider(timespan: int, limit: int = 1000, block_duration: Optional[int] = None)[source]¶
A very simple rate limiting provider - works fine when running a single application instance.
Time values are given in seconds, rather than a timedelta, for improved performance.
timespan – The time in seconds between resetting the number of requests. Beware setting it too high, because memory usage will increase.
limit – The number of requests in the timespan, before getting blocked.
block_duration – If set, the number of seconds before a client is no longer blocked. Otherwise, they’re only removed when the app is restarted.
Making a provider is simple, if the built-in ones don’t meet your needs. A
provider needs to implement a simple interface - see
- class piccolo_api.rate_limiting.middleware.RateLimitProvider[source]¶
An abstract base class which all rate limit providers should inherit from.