{"id":13684569,"url":"https://github.com/usemuffin/throttle","last_synced_at":"2025-12-28T10:45:48.286Z","repository":{"id":31116111,"uuid":"34675617","full_name":"UseMuffin/Throttle","owner":"UseMuffin","description":"(API) Rate limiting requests in CakePHP","archived":false,"fork":false,"pushed_at":"2023-09-23T08:44:45.000Z","size":118,"stargazers_count":63,"open_issues_count":0,"forks_count":13,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-04-17T18:36:18.063Z","etag":null,"topics":["cakephp","cakephp-plugin","middleware","php","rate-limiting"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/UseMuffin.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2015-04-27T15:44:48.000Z","updated_at":"2024-07-26T08:04:18.000Z","dependencies_parsed_at":"2024-01-22T07:48:03.426Z","dependency_job_id":"e97803bb-e9bc-4f76-9446-a08f89de0d96","html_url":"https://github.com/UseMuffin/Throttle","commit_stats":{"total_commits":101,"total_committers":13,"mean_commits":7.769230769230769,"dds":0.4752475247524752,"last_synced_commit":"58d05978949530a8343dbc2febb08ddd1cfb5d58"},"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/UseMuffin%2FThrottle","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/UseMuffin%2FThrottle/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/UseMuffin%2FThrottle/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/UseMuffin%2FThrottle/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/UseMuffin","download_url":"https://codeload.github.com/UseMuffin/Throttle/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251785372,"owners_count":21643464,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cakephp","cakephp-plugin","middleware","php","rate-limiting"],"created_at":"2024-08-02T14:00:35.007Z","updated_at":"2025-12-28T10:45:48.239Z","avatar_url":"https://github.com/UseMuffin.png","language":"PHP","readme":"# Throttle\n\n[![Build Status](https://img.shields.io/github/actions/workflow/status/UseMuffin/Throttle/ci.yml?style=flat-square\u0026branch=master\n)](https://github.com/UseMuffin/Throttle/actions?query=workflow%3ACI+branch%3Amaster)\n[![Coverage Status](https://img.shields.io/codecov/c/github/UseMuffin/Throttle.svg?style=flat-square)](https://codecov.io/github/UseMuffin/Throttle)\n[![Total Downloads](https://img.shields.io/packagist/dt/muffin/throttle.svg?style=flat-square)](https://packagist.org/packages/muffin/throttle)\n[![License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square)](LICENSE)\n\n(API) Rate limiting requests in CakePHP\n\nThis plugin allows you to limit the number of requests a client can make to your\napp in a given time frame.\n\n## Installation\n\n```bash\ncomposer require muffin/throttle\n```\nTo make your application load the plugin either run:\n\n```bash\n./bin/cake plugin load Muffin/Throttle\n```\n\n## Configuration\n\nIn your `config/app.php` add a cache config named `throttle` under the `Cache` key\nwith required config. For e.g.:\n\n```php\n'throttle' =\u003e [\n    'className' =\u003e 'Apcu',\n    'prefix' =\u003e 'throttle_'\n],\n```\n\n### Using the Middleware\n\nAdd the middleware to the queue and pass your custom configuration:\n\n```php\npublic function middleware(MiddlewareQueue $middlewareQueue): MiddlewareQueue\n{\n    // Various other middlewares for error handling, routing etc. added here.\n\n    $throttleMiddleware = new \\Muffin\\Throttle\\Middleware\\ThrottleMiddleware([\n        // Data used to generate response with HTTP code 429 when limit is exceeded.\n        'response' =\u003e [\n            'body' =\u003e 'Rate limit exceeded',\n        ],\n        // Time period as number of seconds\n        'period' =\u003e 60,\n        // Number of requests allowed within the above time period\n        'limit' =\u003e 100,\n        // Client identifier\n        'identifier' =\u003e function ($request) {\n            if (!empty($request-\u003egetHeaderLine('Authorization'))) {\n                return str_replace('Bearer ', '', $request-\u003egetHeaderLine('Authorization'));\n            }\n\n            return $request-\u003eclientIp();\n        }\n    ]);\n\n    $middlewareQueue-\u003eadd($throttleMiddleware);\n\n    return $middlewareQueue;\n}\n```\n\nThe above example would allow 100 requests/minute/token and would first try to\nidentify the client by JWT Bearer token before falling back to (Throttle default)\nIP address based identification.\n\n### Events\n\nThe middleware also dispatches following event which effectively allows you to\nhave multiple rate limits:\n\n#### `Throttle.beforeThrottle`\n\nThis is the first event that is triggered before a request is processed by the\nmiddleware. All rate limiting process will be bypassed if this event is stopped.\n\n```php\n\\Cake\\Event\\EventManager::instance()-\u003eon(\n    \\Muffin\\Throttle\\Middleware\\ThrottleMiddleware::EVENT_BEFORE_THROTTLE,\n    function ($event, $request) {\n        if (/* check for something here, most likely using $request */) {\n            $event-\u003estopPropagation();\n        }\n    }\n);\n```\n\n#### `Throttle.getIdentifier`\n\nInstead of using the `indentifer` config you can also setup a listener for the\n`Throttle.getIdentifier` event. The event's callback would receive a request\ninstance as argument and must return an identifier string.\n\n#### `Throttle.getThrottleInfo`\n\nThe `Throttle.getThrottleInfo` event allows you to customize the `period` and `limit`\nconfigs for a request as well as the cache key used to store the rate limiting info.\n\nThis allows you to set multiple rate limit as per your app's needs.\n\nHere's an example:\n\n```php\n\\Cake\\Event\\EventManager::instance()-\u003eon(\n    \\Muffin\\Throttle\\Middleware\\ThrottleMiddleware::EVENT_GET_THROTTLE_INFO,\n    function ($event, $request, \\Muffin\\Throttle\\ValueObject\\ThrottleInfo $throttle) {\n        // Set a different period for POST request.\n        if ($request-\u003eis('POST')) {\n            // This will change the cache key from default \"{identifer}\" to \"{identifer}.post\".\n            $throttle-\u003eappendToKey('post');\n            $throttle-\u003esetPeriod(30);\n        }\n\n        // Modify limit for logged in user\n        $identity = $request-\u003egetAttribute('identity');\n        if ($identity) {\n            $throttle-\u003eappendToKey($identity-\u003eget('role'));\n            $throttle-\u003esetLimit(200);\n        }\n    }\n);\n```\n\n#### Throtttle.beforeCacheSet\n\nThe `Throtttle.beforeCacheSet` event allows you to observe result of middleware configuration and previous\n`Throtttle.getIdentifier` and `Throttle.getThrottleInfo` events results.\n\nYou can also use this event to modify cached `$rateLimit` and `$ttl` values,\nmodifying `$throttleInfo` in this event has no effect.\n\nExample:\n\n```php\n\\Cake\\Event\\EventManager::instance()-\u003eon(\n    \\Muffin\\Throttle\\Middleware\\ThrottleMiddleware::EVENT_BEFORE_CACHE_SET,\n    function ($event, \\Muffin\\Throttle\\ValueObject\\RateLimitInfo $rateLimit, int $ttl, \\Muffin\\Throttle\\ValueObject\\ThrottleInfo $throttleInfo) {\n        \\Cake\\Log\\Log::debug(sprintf(\"key(%s) remaining(%d) resetTimestamp(%d) ttl(%d)\", $throttleInfo-\u003egetKey(), $rateLimit-\u003egetRemaining(), $rateLimit-\u003egetResetTimestamp(), $ttl));\n    }\n);\n```\n\n### X-headers\n\nBy default Throttle will add X-headers with rate limiting information to all responses:\n\n```\nX-RateLimit-Limit: 10\nX-RateLimit-Remaining: 7\nX-RateLimit-Reset: 1438434161\n```\n\nTo customize the header names simply pass (all of them) under `headers` key in\nyour configuration array:\n\n```php\n'headers' =\u003e [\n    'limit' =\u003e 'X-MyRateLimit-Limit',\n    'remaining' =\u003e 'X-MyRateLimit-Remaining',\n    'reset' =\u003e 'X-MyRateLimit-Reset',\n]\n```\n\nTo disable the headers set `headers` key to `false`.\n\n### Customize response object\n\nYou may use `type` and `headers` subkeys of the `response` array (as you would do\nwith a `Response` object) if you want to return a different message as the default one:\n\n```php\nnew \\Muffin\\Throttle\\Middleware\\ThrottleMiddleware([\n    'response' =\u003e [\n        'body' =\u003e json_encode(['error' =\u003e 'Rate limit exceeded']),\n        'type' =\u003e 'json',\n        'headers' =\u003e [\n            'Custom-Header' =\u003e 'custom_value',\n        ]\n    ],\n    'limit' =\u003e 300,\n]);\n```\n\n## Patches \u0026 Features\n\n* Fork\n* Mod, fix\n* Test - this is important, so it's not unintentionally broken\n* Commit - do not mess with license, todo, version, etc. (if you do change any, bump them into commits of\ntheir own that I can ignore when I pull)\n* Pull request - bonus point for topic branches\n\nTo ensure your PRs are considered for upstream, you MUST follow the CakePHP coding standards.\n\n## Bugs \u0026 Feedback\n\nhttp://github.com/usemuffin/throttle/issues\n\n## License\n\nCopyright (c) 2015-Present, [Use Muffin] and licensed under [The MIT License][mit].\n\n[cakephp]:http://cakephp.org\n[composer]:http://getcomposer.org\n[mit]:http://www.opensource.org/licenses/mit-license.php\n[muffin]:http://usemuffin.com\n","funding_links":[],"categories":["Security"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fusemuffin%2Fthrottle","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fusemuffin%2Fthrottle","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fusemuffin%2Fthrottle/lists"}