NAME

PAGI::FastAPI::Middleware::RateLimit - Async Rate Limiting Middleware for PAGI::FastAPI

VERSION

Version v1.0.0

SYNOPSIS

# Application-wide rate limiting
use PAGI::FastAPI;

my $app = PAGI::FastAPI->new();

$app->add_rate_limit(
    requests => 100,
    window   => 60, # 100 requests per 60 seconds
);

# Custom rate-limiting key based on authenticated user
$app->add_rate_limit(
    requests => 50,
    window   => 30,
    key_cb   => sub ($c) {
        return $c->stash->{user_id} // $c->header('X-API-Key') // 'anonymous';
    },
);

# Direct instantiation
use PAGI::FastAPI::Middleware::RateLimit;

my $limiter = PAGI::FastAPI::Middleware::RateLimit->new(
    requests => 500,
    window   => 3600,
);

$app->add_middleware(async sub ($c, $next) {
    return await $limiter->handle($c, $next);
});

DESCRIPTION

PAGI::FastAPI::Middleware::RateLimit provides asynchronous, non-blocking rate limiting for PAGI::FastAPI applications using fixed time-window counters.

When a client sends a request, the middleware evaluates a unique key identifying the client (e.g., API key or IP address), increments the tracking counter for the active window, and appends standard rate-limiting headers to the HTTP response.

If a client exceeds their allocated quota within the configured timeframe, the middleware short-circuits execution, sets the response status to HTTP 429 Too Many Requests, and returns a standardized JSON error payload detailing the restriction.

HTTP HEADERS

The middleware injects the following response headers into all evaluated requests:

  • x-ratelimit-limit - Maximum number of allowed requests per window.

  • x-ratelimit-remaining - Remaining request quota in the current window.

  • x-ratelimit-reset - Unix timestamp indicating when the current window expires.

When the limit is exceeded (HTTP 429), an additional header is included:

  • retry-after - Number of seconds the client must wait before retrying.

METHODS

new(%options)

Instantiates a new PAGI::FastAPI::Middleware::RateLimit instance. Accepts the following named arguments:

  • requests - Optional integer. Maximum number of allowed requests per window. Default: 100.

  • window - Optional integer. Duration of the rate-limiting window in seconds. Default: 60.

  • key_cb - Optional CODE reference accepting a PAGI::FastAPI::Context instance ($c) and returning a unique scalar string key identifying the client. By default, it falls back through:

    1. X-API-Key request header 2. X-Forwarded-For request header 3. Client connection remote IP address ($c->scope->{client}[0]) 4. Fallback default string '127.0.0.1'

  • driver - Optional storage object implementing increment_async($key, $window), get_async($key) and reset_async($key). Defaults to an instance of PAGI::FastAPI::RateLimit::Driver::Memory.

handle($c, $next)

my $res = await $limiter->handle($c, $next);

Asynchronous method that executes the rate-limiting logic within the request pipeline:

1. Evaluates the client key using key_cb.
2. Queries and increments the request count in the configured driver.
3. Appends standard rate limit HTTP headers (x-ratelimit-*) to $c.
4. Returns an HTTP 429 JSON response if the request limit is exceeded.
5. Awaits and returns $next->($c) if the client is within quota.

ERROR RESPONSE STRUCTURE

When a request is rate-limited (HTTP status 429), the returned JSON structure is:

{
    "detail": "Too Many Requests",
    "message": "API rate limit exceeded. Please try again later.",
    "retry_after": 45
}

AUTHOR

Mohammad Sajid Anwar, <mohammad.anwar at yahoo.com>

REPOSITORY

https://github.com/manwar/PAGI-FastAPI

BUGS

Please report any bugs or feature requests through the web interface at https://github.com/manwar/PAGI-FastAPI/issues. I will be notified and then you'll automatically be notified of progress on your bug as I make changes.

SUPPORT

You can find documentation for this module with the perldoc command.

perldoc PAGI::FastAPI::Middleware::RateLimit

You can also look for information at:

LICENSE AND COPYRIGHT

Copyright (C) 2026 Mohammad Sajid Anwar.

This program is free software; you can redistribute it and/or modify it under the terms of the Artistic License (2.0).