首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Fastapi中的Ratelimit

Fastapi中的Ratelimit
EN

Stack Overflow用户
提问于 2020-12-29 19:09:52
回答 4查看 5.5K关注 0票数 0

如何在Fastapi应用程序中限制API端点请求?我需要为每个用户每秒限制5个API调用请求,并且超过该限制将阻塞该特定用户60秒。

在main.py中

代码语言:javascript
复制
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()

在events.py中

代码语言:javascript
复制
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

在端点中

代码语言:javascript
复制
@router.post('/user',
             tags=["user"],
             name="user:user", dependencies=[Depends(RateLimiter(times=5, seconds=60))])
***code****

从该文件test.py运行。

代码语言:javascript
复制
import uvicorn

from app.main import app

if __name__ == "__main__":
    uvicorn.run("test:app", host="0.0.0.0", port=8000, reload=True)

我按照上面的方式进行了编辑,但得到了以下错误。

代码语言:javascript
复制
File "****ite-packages\starlette\routing.py", line 526, in lifespan
    async for item in self.lifespan_context(app):
  File "****site-packages\starlette\routing.py", line 467, in default_lifespan
    await self.startup()
  File "****site-packages\starlette\routing.py", line 502, in startup
    await handler()
  File "****app\core\services\events.py", line 15, in start_app
    redis = await aioredis.create_redis_pool("redis://localhost:8080")
  File "****\site-packages\aioredis\commands\__init__.py", line 188, in create_redis_pool
    pool = await create_pool(address, db=db,
  File "****site-packages\aioredis\pool.py", line 58, in create_pool
    await pool._fill_free(override_min=False)
  File "C****\site-packages\aioredis\pool.py", line 383, in _fill_free
    conn = await self._create_new_connection(self._address)
  File "****site-packages\aioredis\connection.py", line 111, in create_connection
    reader, writer = await asyncio.wait_for(open_connection(
  File "****\asyncio\tasks.py", line 455, in wait_for
    return await fut
  File "****\site-packages\aioredis\stream.py", line 23, in open_connection
    transport, _ = await get_event_loop().create_connection(
  File "****\asyncio\base_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)
EN

回答 4

Stack Overflow用户

发布于 2020-12-29 19:31:43

最好的选择是使用库,因为FastAPI不提供开箱即用的功能。

slowapi很棒,而且很容易使用。

你可以像这样使用ut。

代码语言:javascript
复制
from fastapi import FastAPI
from slowapi import Limiter, _rate_limit_exceeded_handler
from slowapi.util import get_remote_address


limiter = Limiter(key_func=get_remote_address)
app = FastAPI()
app.state.limiter = limiter
app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler)

@app.get("/home")
@limiter.limit("5/minute")
async def homepage(request: Request):
    return PlainTextResponse("test")

@app.get("/mars")
@limiter.limit("5/minute")
async def homepage(request: Request, response: Response):
    return {"key": "value"}
票数 8
EN

Stack Overflow用户

发布于 2020-12-29 19:31:29

FastAPI本身并不支持这一点,但下面列出的几个库也可以做到这一点,但通常需要某种数据库支持(redis、memcached等),尽管slowapi在没有数据库的情况下有内存后备。

为了使用fastapi-limiter,如他们的文档所示:

注意:您需要一个正在运行的Redis才能正常工作。

代码语言:javascript
复制
import aioredis
import uvicorn
from fastapi import Depends, FastAPI

from fastapi_limiter import FastAPILimiter
from fastapi_limiter.depends import RateLimiter

app = FastAPI()


@app.on_event("startup")
async def startup():
    redis = await aioredis.create_redis_pool("redis://localhost")
    FastAPILimiter.init(redis)


@app.get("/", dependencies=[Depends(RateLimiter(times=2, seconds=5))])
async def index():
    return {"msg": "Hello World"}


if __name__ == "__main__":
    uvicorn.run("main:app", debug=True, reload=True)
票数 3
EN

Stack Overflow用户

发布于 2021-12-31 09:19:02

您可以使用https://github.com/abersheeran/asgi-ratelimit

https://pypi.org/project/fastapi-limiter/https://pypi.org/project/slowapi/相比,它更能满足您的需求。

这是一个例子:超过5次/秒的访问限制后,屏蔽特定用户60秒。

代码语言:javascript
复制
app.add_middleware(
    RateLimitMiddleware,
    authenticate=AUTH_FUNCTION,
    backend=RedisBackend(),
    config={
        r"^/user": [Rule(second=5, block_time=60)],
    },
)
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65491184

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档