aiohttp
Rate-limit middleware using client IP with aiohttp's @web.middleware decorator.
Request Flow
sequenceDiagram
participant C as Client
participant M as rate_limit_middleware
participant RL as RateLimiter
participant H as Handler
C->>M: HTTP Request
M->>RL: allow(request.remote)
alt allowed
RL-->>M: true
M->>H: handler(request)
H-->>M: response
M-->>C: 200 OK
else denied
RL-->>M: false
M-->>C: 429 Rate limit exceeded
end
Code
from aiohttp import web
from rate_limiter import RateLimiter, TokenBucketStrategy
limiter = RateLimiter(lambda: TokenBucketStrategy(capacity=10, rate=2))
@web.middleware
async def rate_limit_middleware(request: web.Request, handler):
key = request.remote or "unknown"
if not await limiter.allow(key):
return web.Response(text="Rate limit exceeded", status=429)
return await handler(request)
async def index(request: web.Request) -> web.Response:
return web.json_response({"message": "Hello, World!"})
app = web.Application(middlewares=[rate_limit_middleware])
app.router.add_get("/", index)
if __name__ == "__main__":
web.run_app(app, port=8080)
aiohttp is natively async, so the middleware awaits the limiter directly — no asyncio.run() bridge needed.