zeroae / zeroae/zae-limiter

✨ FastAPI integration with decorator and dependency injection support

Open
#256 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

area/limiter
Dominant language
Python
Stars
0
Forks
0
Avg merge
6h 51m
Merged PRs (30d)
104

Description

Problem or Use Case

FastAPI is a popular async Python web framework, and users need a native way to integrate zae-limiter into their FastAPI applications. Currently, users must manually wrap rate limiting logic in each endpoint, which is verbose and error-prone.

Common patterns users need:

  • Decorator-based rate limiting: Apply rate limits to routes with minimal boilerplate
  • Dependency injection: Leverage FastAPI's DI system for limiter configuration
  • Request-based entity extraction: Automatically derive entity IDs from headers, query params, or path params
  • Error response handling: Return proper HTTP 429 responses with Retry-After headers

Proposed Solution

Create a zae_limiter.contrib.fastapi module providing native FastAPI integration:

from fastapi import FastAPI, Depends
from zae_limiter import RateLimiter, Limit
from zae_limiter.contrib.fastapi import RateLimitMiddleware, rate_limit, get_limiter

app = FastAPI()

# Option 1: Middleware for global rate limiting
app.add_middleware(
    RateLimitMiddleware,
    limiter=limiter,
    entity_key="X-API-Key",  # Extract from header
    resource="api",
    limits=[Limit.per_minute("rpm", 100)],
)

# Option 2: Decorator for route-level rate limiting
@app.get("/generate")
@rate_limit(
    entity_key="X-API-Key",
    resource="gpt-4",
    limits=[Limit.per_minute("tpm", 10_000)],
)
async def generate(request: Request):
    ...

# Option 3: Dependency injection for fine-grained control
@app.get("/chat")
async def chat(
    limiter: RateLimiter = Depends(get_limiter),
    api_key: str = Header(alias="X-API-Key"),
):
    async with limiter.acquire(entity_id=api_key, resource="gpt-4", ...):
        ...
Entity Key Extraction

Support extracting entity IDs from multiple sources:

from zae_limiter.contrib.fastapi import EntityKey

# From header
entity_key = EntityKey.from_header("X-API-Key")

# From query parameter
entity_key = EntityKey.from_query("api_key")

# From path parameter
entity_key = EntityKey.from_path("user_id")

# From callable (custom extraction)
entity_key = EntityKey.from_callable(lambda request: request.state.user.id)
HTTP 429 Response

When rate limited, return a proper 429 response:

{
  "detail": "Rate limit exceeded",
  "retry_after": 5.2,
  "violations": [
    {"limit": "rpm", "capacity": 100, "remaining": 0}
  ]
}

With Retry-After header set appropriately.

Acceptance Criteria

  • zae_limiter.contrib.fastapi module exists at src/zae_limiter/contrib/fastapi.py
  • RateLimitMiddleware class accepts limiter, entity_key, resource, and limits parameters
  • @rate_limit decorator can be applied to FastAPI route functions
  • EntityKey class has from_header(), from_query(), from_path(), and from_callable() class methods
  • RateLimitExceeded exceptions are converted to HTTP 429 responses with Retry-After header
  • Response body includes detail, retry_after, and violations fields
  • FastAPI is an optional dependency in pyproject.toml under [fastapi] extra
  • Unit tests exist in tests/unit/contrib/test_fastapi.py
  • Integration tests exist in tests/integration/contrib/test_fastapi.py using TestClient
  • Documentation exists at docs/guide/fastapi.md with all three usage patterns
  • API reference docs exist at docs/api/contrib/fastapi.md

Alternatives Considered

  1. Standalone package: Create zae-limiter-fastapi as a separate PyPI package. Rejected because it adds deployment complexity and version coordination overhead.

  2. Generic ASGI middleware only: Provide only ASGI middleware without FastAPI-specific features. Rejected because it misses the opportunity to leverage FastAPI's excellent DI system.

  3. Starlette-only integration: Since FastAPI is built on Starlette, provide only Starlette primitives. This could be a future addition for broader ASGI framework support.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reading the existing limiter API and pyproject.toml, then review the requested entry point at src/zae_limiter/contrib/fastapi.py. Use tests/unit/contrib/test_fastapi.py and tests/integration/contrib/test_fastapi.py as the validation targets, and add the documented usage and API reference in docs/guide/fastapi.md and docs/api/contrib/fastapi.md; done means all listed acceptance criteria are covered.

Written by the indexing model from the issue text.

Assessment

Tech stack
fastapi, python
Domain
api, backend
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.