How to ratelimit API endpoint request in Fastapi application ? I need to ratelimit API call 5 request per second per user and exceeding that limit blocks that particular user for 60 seconds.
In main.py
def get_application() -> FastAPI:
application = FastAPI(title=PROJECT_NAME, debug=DEBUG, version=VERSION)
application.add_event_handler(
"startup", create_start_app_handler(application))
application.add_event_handler(
"shutdown", create_stop_app_handler(application))
return application
app = get_application()
In events.py
def create_start_app_handler(app: FastAPI) -> Callable:
async def start_app() -> None:
redis = await aioredis.create_redis_pool("redis://localhost:8080")
FastAPILimiter.init(redis)
return start_app
In endpoint
@router.post('/user',
tags=["user"],
name="user:user", dependencies=[Depends(RateLimiter(times=5, seconds=60))])
***code****
Run from this file test.py.
import uvicorn
from app.main import app
if __name__ == "__main__":
uvicorn.run("test:app", host="0.0.0.0", port=8000, reload=True)
I edited as above but got following error.
File "****ite-packagesstarletterouting.py", line 526, in lifespan
async for item in self.lifespan_context(app):
File "****site-packagesstarletterouting.py", line 467, in default_lifespan
await self.startup()
File "****site-packagesstarletterouting.py", line 502, in startup
await handler()
File "****appcoreservicesevents.py", line 15, in start_app
redis = await aioredis.create_redis_pool("redis://localhost:8080")
File "****site-packagesaiorediscommands__init__.py", line 188, in create_redis_pool
pool = await create_pool(address, db=db,
File "****site-packagesaioredispool.py", line 58, in create_pool
await pool._fill_free(override_min=False)
File "C****site-packagesaioredispool.py", line 383, in _fill_free
conn = await self._create_new_connection(self._address)
File "****site-packagesaioredisconnection.py", line 111, in create_connection
reader, writer = await asyncio.wait_for(open_connection(
File "****asynciotasks.py", line 455, in wait_for
return await fut
File "****site-packagesaioredisstream.py", line 23, in open_connection
transport, _ = await get_event_loop().create_connection(
File "****asynciobase_events.py", line 1033, in create_connection
raise OSError('Multiple exceptions: {}'.format(
OSError: Multiple exceptions: [Errno 10061] Connect call failed ('::1', 8080, 0, 0), [Errno 10061] Connect call failed ('127.0.0.1', 8080)
4
Answers
FastAPI doesn’t natively support this, but it’s possible with a few libraries such the ones below, but will usually require some sort of database backing(redis, memcached, etc), although slowapi has a memory fallback in case of no database.
In order to use
fastapi-limiter
, as seen in their documentation:Note: You will need a running Redis for this to work.
Best option is using a library since FastAPI does not provide this functionality out-of-box.
slowapi is great, and easy to use.
You can use ut like this.
fastapi-limiter
andslowapi
is very beautiful package to implementRatelimit in Fastapi
.but use
walrus
can also do it. but should startredis
database.start a
redis
.python code: write a python file:
code1228.py
code:
run this python file.
test the link.
http://127.0.0.1:8000/important_api
You can use https://github.com/abersheeran/asgi-ratelimit
Compared to https://pypi.org/project/fastapi-limiter/ and https://pypi.org/project/slowapi/, it can better meet your needs.
This is a example: after exceeding the five times per second access limit, block a specific user for 60 seconds.