{"id":13519729,"url":"https://github.com/beheh/flaps","last_synced_at":"2025-03-31T14:31:03.735Z","repository":{"id":28168848,"uuid":"31670009","full_name":"beheh/flaps","owner":"beheh","description":"🛬 Modular rate limiting for PHP.","archived":true,"fork":false,"pushed_at":"2017-11-21T13:27:14.000Z","size":103,"stargazers_count":63,"open_issues_count":3,"forks_count":12,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-29T10:47:53.303Z","etag":null,"topics":["leaky-bucket","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":"isc","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/beheh.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-03-04T17:27:52.000Z","updated_at":"2024-11-04T02:46:47.000Z","dependencies_parsed_at":"2022-07-31T07:48:01.339Z","dependency_job_id":null,"html_url":"https://github.com/beheh/flaps","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/beheh%2Fflaps","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/beheh%2Fflaps/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/beheh%2Fflaps/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/beheh%2Fflaps/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/beheh","download_url":"https://codeload.github.com/beheh/flaps/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246482937,"owners_count":20784799,"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":["leaky-bucket","php","rate-limiting"],"created_at":"2024-08-01T05:02:02.432Z","updated_at":"2025-03-31T14:31:03.489Z","avatar_url":"https://github.com/beheh.png","language":"PHP","readme":"# Flaps\n\n[![Travis](https://img.shields.io/travis/beheh/flaps/master.svg?style=flat-square)](https://travis-ci.org/beheh/flaps)\n[![Scrutinizer Coverage](https://img.shields.io/scrutinizer/coverage/g/beheh/flaps/master.svg?style=flat-square)](https://scrutinizer-ci.com/g/beheh/flaps/?branch=master)\n[![Scrutinizer](https://img.shields.io/scrutinizer/g/beheh/flaps/master.svg?style=flat-square)](https://scrutinizer-ci.com/g/beheh/flaps/?branch=master)\n[![Packagist](https://img.shields.io/packagist/v/beheh/flaps.svg?style=flat-square)](https://packagist.org/packages/beheh/flaps)\n[![Packagist](https://img.shields.io/packagist/l/beheh/flaps.svg?style=flat-square)](https://packagist.org/packages/beheh/flaps)\n\nFlaps is a modular library for rate limiting requests in PHP applications.\n\nThe library supports custom storage backends, throttling strategies and violation handlers for flexible integration into any project.\n\nDeveloped by [@beheh](https://github.com/beheh) and licensed under the ISC license.\n\n## Requirements\n\n- PHP 5.4 or newer\n- Persistent-ish storage (e.g. Redis, APC or anything supported by _[Doctrine\\Cache](http://doctrine-common.readthedocs.org/en/latest/reference/caching.html)_)\n- Composer\n\n## Basic usage\n\n```php\nuse Predis\\Client;\nuse BehEh\\Flaps\\Storage\\PredisStorage;\nuse BehEh\\Flaps\\Flaps;\nuse BehEh\\Flaps\\Throttling\\LeakyBucketStrategy;\n\n// setup with Redis as storage backend\n$storage = new PredisStorage(new Client());\n$flaps = new Flaps($storage);\n\n// allow 3 requests per 5 seconds\n$flaps-\u003elogin-\u003epushThrottlingStrategy(new LeakyBucketStrategy(3, '5s'));\n//or $flaps-\u003e__get('login')-\u003epushThrottlingStrategy(...)\n\n// limit by ip (default: send \"HTTP/1.1 429 Too Many Requests\" and die() on violation)\n$flaps-\u003elogin-\u003elimit($_SERVER['REMOTE_ADDR']);\n```\n\n## Why rate limit?\n\nThere are many benefits from rate limiting your web application. At any point in time your server(s) could be hit by a huge number of requests from one or many clients. These could be:\n- Malicious clients trying to degrade your applications performance\n- Malicious clients bruteforcing user credentials\n- Bugged clients repeating requests over and over again\n- Automated web crawlers enumerating usernames or email adresses\n- Penetration frameworks testing for vulnerabilities\n- Bots registering a large number of users\n- Bots spamming links to malicious sites\n\nMost of these problems can be solved in a variety of ways, for example by using a spam filter or a fully configured firewall. Rate limiting is nevertheless a basic tool for improving application security, but offers no full protection.\n\n## Advanced examples\n\n### Application-handled violation\n\n```php\nuse BehEh\\Flaps\\Throttling\\LeakyBucketStrategy;\nuse BehEh\\Flaps\\Violation\\PassiveViolationHandler;\n\n$flap = $flaps-\u003e__get('api');\n$flap-\u003epushThrottlingStrategy(new LeakyBucketStrategy(15, '10s'));\n$flap-\u003esetViolationHandler(new PassiveViolationHandler);\nif (!$flap-\u003elimit(filter_var(INPUT_GET, 'api_key'))) {\n\tdie(json_encode(array('error' =\u003e 'too many requests')));\n}\n```\n\n### Multiple throttling strategies\n\n```php\nuse BehEh\\Flaps\\Throttling\\LeakyBucketStrategy;\n\n$flap = $flaps-\u003e__get('add_comment');\n$flap-\u003epushThrottlingStrategy(new LeakyBucketStrategy(1, '30s'));\n$flap-\u003epushThrottlingStrategy(new LeakyBucketStrategy(10, '10m'));\n$flap-\u003elimit($userid);\n```\n\n## Storage\n\n### Redis\n\nThe easiest storage system to get started is Redis (via [nrk/predis](https://github.com/nrk/predis)):\n\n```php\nuse Predis\\Client;\nuse BehEh\\Flaps\\Storage\\PredisStorage;\nuse BehEh\\Flaps\\Flaps;\n\n$storage = new PredisStorage(new Client('tcp://10.0.0.1:6379'));\n$flaps = new Flaps($storage);\n```\n\nDon't forget to `composer require predis/predis`.\n\n### Doctrine cache\n\nYou can use any of the [Doctrine cache implementations](http://doctrine-common.readthedocs.org/en/latest/reference/caching.html) by using the _DoctrineCacheAdapter_:\n\n```php\nuse Doctrine\\Common\\Cache\\ApcCache;\nuse BehEh\\Flaps\\Storage\\DoctrineCacheAdapter;\nuse BehEh\\Flaps\\Flaps;\n\n$apc = new ApcCache();\n$apc-\u003esetNamespace('MyApplication');\n$storage = new DoctrineCacheAdapter($apc);\n$flaps = new Flaps($storage);\n```\n\nThe Doctrine caching implementations can be installed with `composer require doctrine/cache`.\n\n### Custom storage\n\nAlternatively you can use your own storage system by implementing _BehEh\\Flaps\\StorageInterface_.\n\n## Throttling strategies\n\n### Leaky bucket strategy\n\nThis strategy is based on the leaky bucket algorithm. Each unique identifier of a flap corresponds to a leaky bucket.\nClients can now access the buckets as much as they like, inserting water for every request. If a request would cause the bucket to overflow, it is denied.\nIn order to allow later requests, the bucket leaks at a fixed rate.\n\n```php\nuse BehEh\\Flaps\\Throttle\\LeakyBucketStrategy;\n\n$flap-\u003epushThrottlingStrategy(new LeakyBucketStrategy(60, '10m'));\n```\n\n### Custom throttling strategy\n\nOnce again, you can supply your own throttling strategy by implementing _BehEh\\Flaps\\ThrottlingStrategyInterface_.\n\n## Violation handler\n\nYou can handle violations either using one of the included handlers or by writing your own.\n\n## HTTP violation handler\n\nThe HTTP violation handler is the most basic violation handler, recommended for simple scripts.\nIt simply sends the correct HTTP header (status code 429) and die()s. This is not recommended for any larger application and should be replaced by one of the more customizable handlers.\n\n```php\nuse BehEh\\Flaps\\Violation\\HttpViolationHandler;\n\n$flap-\u003esetViolationHandler(new HttpViolationHandler);\n$flap-\u003elimit($identifier);  // send \"HTTP/1.1 429 Too Many Requests\" and die() on violation\n```\n\n## Passive violation handler\n\nThe passive violation handler allows you to easily react to violations.\n`limit()` will return false if the requests violates any throttling strategy, so you are able to log the request or return a custom error page.\n\n```php\nuse BehEh\\Flaps\\Violation\\PassiveViolationHandler;\n\n$flap-\u003esetViolationHandler(new PassiveViolationHandler);\nif (!$flap-\u003elimit($identifier)) {\n\t// violation\n}\n```\n\n### Exception violation handler\n\nThe exception violation handler can be used in larger frameworks. It will throw a _ThrottlingViolationException_ whenever a _ThrottlingStrategy_ is violated.\nYou should be able to setup your exception handler to catch any _ThrottlingViolationException_.\n\n```php\nuse BehEh\\Flaps\\Violation\\ExceptionViolationHandler;\nuse BehEh\\Flaps\\Violation\\ThrottlingViolationException;\n\n$flap-\u003esetViolationHandler(new ExceptionViolationHandler);\ntry {\n\t$flap-\u003elimit($identifier); // throws ThrottlingViolationException on violation\n}\ncatch (ThrottlingViolationException $e) {\n\t// violation\n}\n```\n\n### Custom violation handler\n\nThe corresponding interface for custom violation handlers is _BehEh\\Flaps\\ViolationHandlerInterface_.\n\n### Default violation handler\n\nThe `Flaps` object can pass a default violation handler to the flaps.\n\n```php\n$flaps-\u003esetDefaultViolationHandler(new CustomViolationHandler);\n\n$flap = $flaps-\u003e__get('login');\n$flap-\u003eaddThrottlingStrategy(new TimeBasedThrottlingStrategy(1, '1s'));\n$flap-\u003elimit($identifier); // will use CustomViolationHandler\n```\n","funding_links":[],"categories":["PHP"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbeheh%2Fflaps","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbeheh%2Fflaps","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbeheh%2Fflaps/lists"}