2017 © Pedro Peláez
 

cakephp-plugin throttle

(API) Rate limiting requests in CakePHP 3

image

muffin/throttle

(API) Rate limiting requests in CakePHP 3

  • Monday, April 23, 2018
  • by ADmad
  • Repository
  • 7 Watchers
  • 47 Stars
  • 2,646 Installations
  • PHP
  • 1 Dependents
  • 0 Suggesters
  • 12 Forks
  • 1 Open issues
  • 5 Versions
  • 5 % Grown

The README.md

Throttle

Build Status Coverage Status Total Downloads License, (*1)

(API) Rate limiting requests in CakePHP, (*2)

This plugin allows you to limit the number of requests a client can make to your app in a given time frame., (*3)

Installation

composer require muffin/throttle

To make your application load the plugin either run:, (*4)

./bin/cake plugin load Muffin/Throttle

Configuration

In your config/app.php add a cache config named throttle under the Cache key with required config. For e.g.:, (*5)

'throttle' => [
    'className' => 'Apcu',
    'prefix' => 'throttle_'
],

Using the Middleware

Add the middleware to the queue and pass your custom configuration:, (*6)

public function middleware(MiddlewareQueue $middlewareQueue): MiddlewareQueue
{
    // Various other middlewares for error handling, routing etc. added here.

    $throttleMiddleware = new \Muffin\Throttle\Middleware\ThrottleMiddleware([
        // Data used to generate response with HTTP code 429 when limit is exceeded.
        'response' => [
            'body' => 'Rate limit exceeded',
        ],
        // Time period as number of seconds
        'period' => 60,
        // Number of requests allowed within the above time period
        'limit' => 100,
        // Client identifier
        'identifier' => function ($request) {
            if (!empty($request->getHeaderLine('Authorization'))) {
                return str_replace('Bearer ', '', $request->getHeaderLine('Authorization'));
            }

            return $request->clientIp();
        }
    ]);

    $middlewareQueue->add($throttleMiddleware);

    return $middlewareQueue;
}

The above example would allow 100 requests/minute/token and would first try to identify the client by JWT Bearer token before falling back to (Throttle default) IP address based identification., (*7)

Events

The middleware also dispatches following event which effectively allows you to have multiple rate limits:, (*8)

Throttle.beforeThrottle

This is the first event that is triggered before a request is processed by the middleware. All rate limiting process will be bypassed if this event is stopped., (*9)

\Cake\Event\EventManager::instance()->on(
    \Muffin\Throttle\Middleware\ThrottleMiddleware::EVENT_BEFORE_THROTTLE,
    function ($event, $request) {
        if (/* check for something here, most likely using $request */) {
            $event->stopPropogation();
        }
    }
);

Throttle.getIdentifier

Instead of using the indentifer config you can also setup a listener for the Throttle.getIdentifier event. The event's callback would receive a request instance as argument and must return an identifier string., (*10)

Throttle.getThrottleInfo

The Throttle.getThrottleInfo event allows you to customize the period and limit configs for a request as well as the cache key used to store the rate limiting info., (*11)

This allows you to set multiple rate limit as per your app's needs., (*12)

Here's an example:, (*13)

\Cake\Event\EventManager::instance()->on(
    \Muffin\Throttle\Middleware\ThrottleMiddleware::EVENT_GET_THROTTLE_INFO,
    function ($event, $request, \Muffin\Throttle\ValueObject\ThrottleInfo $throttle) {
        // Set a different period for POST request.
        if ($request->is('POST')) {
            // This will change the cache key from default "{identifer}" to "{identifer}.post".
            $throttle->appendToKey('post');
            $throttle->setPeriod(30);
        }

        // Modify limit for logged in user
        $identity = $request->getAttribute('identity');
        if ($identity) {
            $throttle->appendToKey($identity->get('role'));
            $throttle->setLimit(200);
        }
    }
);

Throtttle.beforeCacheSet

The Throtttle.beforeCacheSet event allows you to observe result of middleware configuration and previous Throtttle.getIdentifier and Throttle.getThrottleInfo events results., (*14)

You can also use this event to modify cached $rateLimit and $ttl values, modifying $throttleInfo in this event has no effect., (*15)

Example:, (*16)

\Cake\Event\EventManager::instance()->on(
    \Muffin\Throttle\Middleware\ThrottleMiddleware::EVENT_BEFORE_CACHE_SET,
    function ($event, \Muffin\Throttle\ValueObject\RateLimitInfo $rateLimit, int $ttl, \Muffin\Throttle\ValueObject\ThrottleInfo $throttleInfo) {
        \Cake\Log\Log::debug(sprintf("key(%s) remaining(%d) resetTimestamp(%d) ttl(%d)", $throttleInfo->getKey(), $rateLimit->getRemaining(), $rateLimit->getResetTimestamp(), $ttl));
    }
);

X-headers

By default Throttle will add X-headers with rate limiting information to all responses:, (*17)

X-RateLimit-Limit: 10
X-RateLimit-Remaining: 7
X-RateLimit-Reset: 1438434161

To customize the header names simply pass (all of them) under headers key in your configuration array:, (*18)

'headers' => [
    'limit' => 'X-MyRateLimit-Limit',
    'remaining' => 'X-MyRateLimit-Remaining',
    'reset' => 'X-MyRateLimit-Reset',
]

To disable the headers set headers key to false., (*19)

Customize response object

You may use type and headers subkeys of the response array (as you would do with a Response object) if you want to return a different message as the default one:, (*20)

new \Muffin\Throttle\Middleware\ThrottleMiddleware([
    'response' => [
        'body' => json_encode(['error' => 'Rate limit exceeded']),
        'type' => 'json',
        'headers' => [
            'Custom-Header' => 'custom_value',
        ]
    ],
    'limit' => 300,
]);

Patches & Features

  • Fork
  • Mod, fix
  • Test - this is important, so it's not unintentionally broken
  • Commit - do not mess with license, todo, version, etc. (if you do change any, bump them into commits of their own that I can ignore when I pull)
  • Pull request - bonus point for topic branches

To ensure your PRs are considered for upstream, you MUST follow the CakePHP coding standards., (*21)

Bugs & Feedback

http://github.com/usemuffin/throttle/issues, (*22)

License

Copyright (c) 2015-Present, [Use Muffin] and licensed under The MIT License., (*23)

The Versions

23/04 2018

dev-master

9999999-dev https://github.com/usemuffin/throttle

(API) Rate limiting requests in CakePHP 3

  Sources   Download

MIT

The Requires

 

The Development Requires

cakephp throttle rate limit muffin

23/04 2018

1.2.0

1.2.0.0 https://github.com/usemuffin/throttle

(API) Rate limiting requests in CakePHP 3

  Sources   Download

MIT

The Requires

 

The Development Requires

cakephp throttle rate limit muffin

23/04 2018

dev-dev

dev-dev https://github.com/usemuffin/throttle

(API) Rate limiting requests in CakePHP 3

  Sources   Download

MIT

The Requires

 

The Development Requires

cakephp throttle rate limit muffin

10/03 2017

1.1.0

1.1.0.0 https://github.com/usemuffin/throttle

(API) Rate limiting requests in CakePHP 3

  Sources   Download

MIT

The Requires

 

The Development Requires

cakephp throttle rate limit muffin

04/01 2017

1.0.0

1.0.0.0 https://github.com/usemuffin/throttle

(API) Rate limiting requests in CakePHP 3

  Sources   Download

MIT

The Development Requires

cakephp throttle rate limit muffin