Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Rate Limit Bundle Laravel Package

coka/rate-limit-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation

    composer require coka/rate-limit-bundle
    

    Enable the bundle in config/bundles.php:

    CedrickOka\RateLimitBundle\CedrickOkaRateLimitBundle::class => ['all' => true],
    
  2. Basic Configuration Add to config/packages/cedrick_oka_rate_limit.yaml:

    cedrick_oka_rate_limit:
        limits:
            default: 100 # Requests per minute
        storage: cache # Options: cache, redis, database
    
  3. First Use Case Apply rate limiting to a controller method:

    use CedrickOka\RateLimitBundle\Annotation\RateLimit;
    
    class ApiController extends AbstractController
    {
        /**
         * @RateLimit(limit=50, time=60)
         */
        public function sensitiveEndpoint()
        {
            return new JsonResponse(['data' => '...']);
        }
    }
    

Implementation Patterns

Common Workflows

  1. Annotation-Based Limiting Use @RateLimit on controller methods or classes:

    /**
     * @RateLimit(limit=10, time=300, message="Too many requests")
     */
    public function login()
    {
        // ...
    }
    
  2. Dynamic Limits via Middleware Override limits programmatically:

    public function handle(Request $request, Closure $next)
    {
        $request->attributes->set('rate_limit', [
            'limit' => 200, // Override
            'time' => 3600,
        ]);
        return $next($request);
    }
    
  3. Storage Backends

    • Cache: Fast, in-memory (default).
    • Redis: Scalable, persistent.
    • Database: Durable but slower. Configure in config/packages/cedrick_oka_rate_limit.yaml:
    storage: redis
    redis:
        dsn: "redis://localhost:6379"
    
  4. Event-Based Extensions Listen to rate_limit.exceeded events for custom responses:

    public function onRateLimitExceeded(RateLimitExceededEvent $event)
    {
        $event->setResponse(new JsonResponse(['error' => 'Custom message'], 429));
    }
    

Gotchas and Tips

Pitfalls

  1. Caching Quirks

    • Cache backend uses default cache by default. Ensure cache:clear is run after config changes.
    • Redis keys may collide if not namespaced. Use namespace: "app_" in config.
  2. Annotation Parsing

    • Clear Symfony cache after adding @RateLimit annotations:
      php bin/console cache:clear
      
    • Class-level annotations override method-level ones.
  3. Performance

    • Database storage adds ~100ms latency. Use Redis for production.
    • Avoid excessive time values (e.g., time=86400 for daily limits) in cache backends.
  4. CORS Headers The bundle auto-adds X-RateLimit-* headers but does not handle CORS policies. Configure manually in config/packages/nelmio_cors.yaml if needed.

Debugging Tips

  • Check Limits Log the current limit state in middleware:
    $limit = $request->attributes->get('rate_limit');
    $this->logger->debug('Rate limit', ['limit' => $limit]);
    
  • Redis Debugging Use redis-cli to inspect keys:
    redis-cli KEYS "rate_limit:*"
    
  • Event Debugging Temporarily override the rate_limit.exceeded event to log details:
    $event->getRequest()->attributes->get('rate_limit');
    

Extension Points

  1. Custom Storage Implement CedrickOka\RateLimitBundle\Storage\StorageInterface:

    class CustomStorage implements StorageInterface
    {
        public function increment($key, $limit, $time)
        {
            // Custom logic (e.g., database)
        }
    }
    

    Register in config:

    storage: custom
    custom:
        class: App\Storage\CustomStorage
    
  2. Response Customization Extend the RateLimitListener to modify responses:

    public function onKernelException(GetResponseForExceptionEvent $event)
    {
        if ($event->getException() instanceof RateLimitExceededException) {
            $event->setResponse(new Response('Custom 429', 429, [
                'X-Custom-Header' => 'value',
            ]));
        }
    }
    
  3. IP-Based vs. Token-Based Override the getKey() method in a custom listener to use tokens (e.g., API keys) instead of IPs:

    $key = $request->headers->get('X-API-KEY') ?: $request->getClientIp();
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator
equipc/laravel-email-database-log
adedsec/nova-translated-labels
wazza/laravel-db-encryption
hokny/laravel-generator
vonsogt/backup
jengo/queues
jeremykenedy/laravel-observability
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums