Search by

phil / rate-limit-bundle

phil

Rate limits declared on Symfony controllers, routes and forms: an attribute, a route default and a form option naming limiters over symfony/rate-limiter, keys hashed from the client's address or the user, 429 answers with Retry-After and the IETF RateLimit headers, JSON problems for APIs, a Twig pag

Package info

github.com/parler-haut-interagir-librement/rate-limit-bundle

Homepage

Type:symfony-bundle

pkg:composer/phil/rate-limit-bundle

Statistics

Installs: 11

Dependents: 1

Suggesters: 1

Stars: 0

Open Issues: 0

0.1.0-alpha 2026-11-12 14:43 UTC

This package is auto-updated.

Last update: 2026-11-12 23:52:03 UTC


README

Rate limits declared on Symfony controllers, routes and forms.

phil/rate-limit-bundle holds requests to named limiters: #[RateLimit] on a controller or an action, the route default _rate_limit, and the rate_limit option of a form. The limiters are fixed windows, sliding windows, token buckets and compounds of symfony/rate-limiter, declared in the bundle's configuration with their storage, or those of other packages. Each request counts under a key — the client's address, the signed-in user, the address and the route, or the application's own —, always a keyed hash, never an address in clear. A refusal is answered 429 Too Many Requests with Retry-After and the RateLimit-Policy and RateLimit fields of the IETF draft: a problem in JSON to an API, a Twig page to a browser, an error on the form. Each refusal is dispatched as an event.

Status

Part State
#[RateLimit] on classes and actions, the route default _rate_limit Implemented and tested
Fixed window, sliding window, token bucket, compound and factory limiters, checked at build Implemented and tested
Keys ip, user, user_or_ip, ip_route and the application's, the network with phil/ip-anonymizer Implemented and tested
429 with Retry-After, draft or legacy RateLimit headers, problem JSON, Twig page in English and French Implemented and tested
Form submissions limited by form name Implemented and tested
The RateLimitExceeded event, limiters of other packages by tag Implemented and tested
Limiters in observation: the RateLimitObserved event and a warning, without refusing Implemented and tested
A store local to each server refused in prod, with the guard of phil/rate-limit Implemented and tested

Documentation

Document What it covers
Installation Requirements, the bundle, the storage.
Configuration Every option, with an example.
Limiting requests The attribute, the route default, the order of the rules.
Keys Who a request counts for, and how the keys are hashed.
Responses The 429, its headers, the problem in JSON, the page, the event.
Forms Limiting the submissions of a form by its name.
Extension points Limiters, key strategies, the event, the template.
Testing The bundle's tests and its benchmark.
Reference Every class and file of the bundle.

Quick start

// config/bundles.php
Phil\RateLimitBundle\PhilRateLimitBundle::class => ['all' => true],
# config/packages/phil_rate_limit.yaml
phil_rate_limit:
    cache_pool: cache.rate_limits
    limiters:
        api: { policy: sliding_window, limit: 100, interval: '1 minute' }
        login: { policy: fixed_window, limit: 5, interval: '15 minutes', key: ip_route }
        contact: { policy: token_bucket, limit: 3, rate: { interval: '10 minutes' } }
    forms:
        contact: contact
use Phil\RateLimitBundle\Domain\Attribute\RateLimit;

#[RateLimit('api')]
final class SearchController
{
    #[RateLimit('login')]
    public function login(): Response
}

Requirements

PHP 8.5 or later and Symfony 8.2 or later with FrameworkBundle; TwigBundle for the refusal page, the form component for forms, security for the user keys, phil/ip-anonymizer for network keys, a PSR-3 logger for the warnings of a limiter in observation. phil/rate-limit, required, guards the stores in production.

Contributing

Contributions are welcome on the PHIL monorepo: read the contribution guide and the code of conduct. Report a vulnerability privately, as the security policy explains, never in a public issue.

License

MIT, © Philippe Gamache, doing business as Le Gnome Archiviste; a Parler Haut Interagir Librement project. See LICENSE.