Skip to main content

A simple rate limiter for FastAPI.

Project description

Act-Ratelimit

pypi license workflows workflows

Introduction

FastAPI-Limiter is a rate limiting tool for fastapi routes with lua script.

Requirements

Install

Just install from pypi

> pip install fastapi-limiter

Quick Start

FastAPI-Limiter is simple to use, which just provide a dependency RateLimiter, the following example allow 2 times request per 5 seconds in route /.

import redis.asyncio as redis
import uvicorn
from contextlib import asynccontextmanager
from fastapi import Depends, FastAPI

from fastapi_ratelimit import FastAPILimiter
from fastapi_ratelimit.depends import RateLimiter


@asynccontextmanager
async def lifespan(_: FastAPI):
    redis_connection = redis.from_url("redis://localhost:6379", encoding="utf8")
    await FastAPILimiter.init(redis_connection)
    yield
    await FastAPILimiter.close()


app = FastAPI(lifespan=lifespan)


@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)

Usage

There are some config in FastAPILimiter.init.

redis

The redis instance of aioredis.

prefix

Prefix of redis key.

identifier

Identifier of route limit, default is ip, you can override it such as userid and so on.

async def default_identifier(request: Request):
    forwarded = request.headers.get("X-Forwarded-For")
    if forwarded:
        return forwarded.split(",")[0]
    return request.client.host + ":" + request.scope["path"]

callback

Callback when access is forbidden, default is raise HTTPException with 429 status code.

async def default_callback(request: Request, response: Response, pexpire: int):
    """
    default callback when too many requests
    :param request:
    :param pexpire: The remaining milliseconds
    :param response:
    :return:
    """
    expire = ceil(pexpire / 1000)

    raise HTTPException(
        HTTP_429_TOO_MANY_REQUESTS, "Too Many Requests", headers={"Retry-After": str(expire)}
    )

Multiple limiters

You can use multiple limiters in one route.

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

Not that you should note the dependencies orders, keep lower of result of seconds/times at the first.

Rate limiting within a websocket.

While the above examples work with rest requests, FastAPI also allows easy usage of websockets, which require a slightly different approach.

Because websockets are likely to be long lived, you may want to rate limit in response to data sent over the socket.

You can do this by rate limiting within the body of the websocket handler:

@app.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket):
    await websocket.accept()
    ratelimit = WebSocketRateLimiter(times=1, seconds=5)
    while True:
        try:
            data = await websocket.receive_text()
            await ratelimit(websocket, context_key=data)  # NB: context_key is optional
            await websocket.send_text(f"Hello, world")
        except WebSocketRateLimitException:  # Thrown when rate limit exceeded.
            await websocket.send_text(f"Hello again")

Lua script

The lua script used.

local key = KEYS[1]
local limit = tonumber(ARGV[1])
local expire_time = ARGV[2]

local current = tonumber(redis.call('get', key) or "0")
if current > 0 then
    if current + 1 > limit then
        return redis.call("PTTL", key)
    else
        redis.call("INCR", key)
        return 0
    end
else
    redis.call("SET", key, 1, "px", expire_time)
    return 0
end

License

This project is licensed under the Apache-2.0 License.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

act_ratelimit-0.1.tar.gz (14.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

act_ratelimit-0.1-py3-none-any.whl (11.4 kB view details)

Uploaded Python 3

File details

Details for the file act_ratelimit-0.1.tar.gz.

File metadata

  • Download URL: act_ratelimit-0.1.tar.gz
  • Upload date:
  • Size: 14.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: python-requests/2.32.3

File hashes

Hashes for act_ratelimit-0.1.tar.gz
Algorithm Hash digest
SHA256 0f8acdaf9014d9220023c4696e4626ce815767d840a26a6ed66ec036af8b9ee1
MD5 367907d572af809c56ed53d3fc582495
BLAKE2b-256 7b293c62f2306545008a9699bee923a8695b3752d9a6d25e6b9896c1912c61ab

See more details on using hashes here.

File details

Details for the file act_ratelimit-0.1-py3-none-any.whl.

File metadata

  • Download URL: act_ratelimit-0.1-py3-none-any.whl
  • Upload date:
  • Size: 11.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: python-requests/2.32.3

File hashes

Hashes for act_ratelimit-0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 fc9c705e451c5b5f08b94a7b83534d8f25d8710b212988ddf1ee5fe2cb5dc5c2
MD5 ba919ecbc38b23ce6378d70f7c17b1db
BLAKE2b-256 a6b867784f84b94134f149b784703fa5b5b4659ab14a9aa974c56f12413be6be

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page