Repository: spatie/guzzle-rate-limiter-middleware
Branch: main
Commit: 3626aa5bb584
Files: 21
Total size: 19.9 KB
Directory structure:
gitextract_wrtnnr9r/
├── .editorconfig
├── .gitattributes
├── .gitignore
├── .scrutinizer.yml
├── .styleci.yml
├── .travis.yml
├── CHANGELOG.md
├── LICENSE.md
├── README.md
├── composer.json
├── phpunit.xml.dist
├── src/
│ ├── Deferrer.php
│ ├── InMemoryStore.php
│ ├── RateLimiter.php
│ ├── RateLimiterMiddleware.php
│ ├── SleepDeferrer.php
│ └── Store.php
└── tests/
├── RateLimiterMiddlewareTest.php
├── RateLimiterTest.php
├── TestCase.php
└── TestDeferrer.php
================================================
FILE CONTENTS
================================================
================================================
FILE: .editorconfig
================================================
; This file is for unifying the coding style for different editors and IDEs.
; More information at https://editorconfig.org
root = true
[*]
charset = utf-8
indent_size = 4
indent_style = space
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
[*.md]
trim_trailing_whitespace = false
================================================
FILE: .gitattributes
================================================
# Path-based git attributes
# https://www.kernel.org/pub/software/scm/git/docs/gitattributes.html
# Ignore all test and documentation with "export-ignore".
/.gitattributes export-ignore
/.gitignore export-ignore
/.travis.yml export-ignore
/phpunit.xml.dist export-ignore
/.scrutinizer.yml export-ignore
/tests export-ignore
/.editorconfig export-ignore
================================================
FILE: .gitignore
================================================
build
composer.lock
docs
vendor
coverage
.phpunit.result.cache
================================================
FILE: .scrutinizer.yml
================================================
filter:
excluded_paths: [tests/*]
checks:
php:
remove_extra_empty_lines: true
remove_php_closing_tag: true
remove_trailing_whitespace: true
fix_use_statements:
remove_unused: true
preserve_multiple: false
preserve_blanklines: true
order_alphabetically: true
fix_php_opening_tag: true
fix_linefeed: true
fix_line_ending: true
fix_identation_4spaces: true
fix_doc_comments: true
================================================
FILE: .styleci.yml
================================================
preset: laravel
disabled:
- single_class_element_per_statement
================================================
FILE: .travis.yml
================================================
language: php
php:
- 7.1
- 7.2
- 7.3
- 8.0
- 8.1
- 8.2
- 8.3
- 8.4
env:
matrix:
- COMPOSER_FLAGS="--prefer-lowest"
- COMPOSER_FLAGS=""
before_script:
- travis_retry composer self-update
- travis_retry composer update ${COMPOSER_FLAGS} --no-interaction --prefer-source
script:
- vendor/bin/phpunit --coverage-text --coverage-clover=coverage.clover
after_script:
- php vendor/bin/ocular code-coverage:upload --format=php-clover coverage.clover
================================================
FILE: CHANGELOG.md
================================================
# Changelog
All notable changes to `guzzle-rate-limiter-middleware` will be documented in this file
## 2.0.1 - 2020-12-19
- add support for PHP 8
## 2.0.0 - 2020-10-06
- Pass a `$limit` parameter in `Store::push`, the signature is now `Store::push(int $timestamp, int $limit)`
- Allow custom `Deferrer` instances to be passed to `RateLimiterMiddleware::perMinute` and `RateLimiterMiddleware::perSecond`
## 1.0.8 - 2020-07-16
- Allow Guzzle 7
## 1.0.7 - 2020-01-09
- Cast return value of SleepDeferrer to int (#7)
## 1.0.1 - 2019-10-25
- use usleep to ensure sleep actually happens (#5)
## 1.0.0 - 2019-10-08
- initial release
================================================
FILE: LICENSE.md
================================================
The MIT License (MIT)
Copyright (c) Spatie bvba <info@spatie.be>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
================================================
FILE: README.md
================================================
# A rate limiter middleware for Guzzle
[](https://packagist.org/packages/spatie/guzzle-rate-limiter-middleware)
[](https://travis-ci.org/spatie/guzzle-rate-limiter-middleware)
[](https://scrutinizer-ci.com/g/spatie/guzzle-rate-limiter-middleware)
[](https://github.styleci.io/repos/165693657)
[](https://packagist.org/packages/spatie/guzzle-rate-limiter-middleware)
A rate limiter middleware for Guzzle. Here's what you need to know:
- Specify a maximum amount of requests per minute or per second
- When the limit is reached, the process will `sleep` until the request can be made
- Implement your own driver to persist the rate limiter's request store. This is necessary if the rate limiter needs to work across separate processes, the package ships with an `InMemoryStore`.
## Support us
[<img src="https://github-ads.s3.eu-central-1.amazonaws.com/guzzle-rate-limiter-middleware.jpg?t=1" width="419px" />](https://spatie.be/github-ad-click/guzzle-rate-limiter-middleware)
We invest a lot of resources into creating [best in class open source packages](https://spatie.be/open-source). You can support us by [buying one of our paid products](https://spatie.be/open-source/support-us).
We highly appreciate you sending us a postcard from your hometown, mentioning which of our package(s) you are using. You'll find our address on [our contact page](https://spatie.be/about-us). We publish all received postcards on [our virtual postcard wall](https://spatie.be/open-source/postcards).
## Installation
You can install the package via composer:
```bash
composer require spatie/guzzle-rate-limiter-middleware
```
## Usage
Create a [Guzzle middleware stack](http://docs.guzzlephp.org/en/stable/handlers-and-middleware.html) and register it on the client.
```php
use GuzzleHttp\Client;
use GuzzleHttp\HandlerStack;
use Spatie\GuzzleRateLimiterMiddleware\RateLimiterMiddleware;
$stack = HandlerStack::create();
$stack->push(RateLimiterMiddleware::perSecond(3));
$client = new Client([
'handler' => $stack,
]);
```
You can create a rate limiter to limit per second or per minute.
```php
RateLimiterMiddleware::perSecond(3); // Max. 3 requests per second
RateLimiterMiddleware::perMinute(5); // Max. 5 requests per minute
```
## Custom stores
By default, the rate limiter works in memory. This means that if you have a second PHP process (or Guzzle client) consuming the same API, you'd still possibly hit the rate limit. To work around this issue, the rate limiter's state should be persisted to a cache. Implement the `Store` interface with your own cache, and pass the store to the rate limiter.
```php
use MyApp\RateLimiterStore;
use Spatie\GuzzleRateLimiterMiddleware\RateLimit;
RateLimiterMiddleware::perSecond(3, new RateLimiterStore());
```
A Laravel example of a custom `Store`:
```php
<?php
namespace MyApp;
use Spatie\GuzzleRateLimiterMiddleware\Store;
use Illuminate\Support\Facades\Cache;
class RateLimiterStore implements Store
{
public function get(): array
{
return Cache::get('rate-limiter', []);
}
public function push(int $timestamp, int $limit)
{
Cache::put('rate-limiter', array_merge($this->get(), [$timestamp]));
}
}
```
### Testing
``` bash
composer test
```
### Changelog
Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.
## Contributing
Please see [CONTRIBUTING](https://github.com/spatie/.github/blob/main/CONTRIBUTING.md) for details.
### Security
If you've found a bug regarding security please mail [security@spatie.be](mailto:security@spatie.be) instead of using the issue tracker.
## Postcardware
You're free to use this package, but if it makes it to your production environment we highly appreciate you sending us a postcard from your hometown, mentioning which of our package(s) you are using.
Our address is: Spatie, Kruikstraat 22, 2018 Antwerp, Belgium.
We publish all received postcards [on our company website](https://spatie.be/en/opensource/postcards).
## Credits
- [Sebastian De Deyne](https://github.com/sebastiandedeyne)
- [All Contributors](../../contributors)
## License
The MIT License (MIT). Please see [License File](LICENSE.md) for more information.
================================================
FILE: composer.json
================================================
{
"name": "spatie/guzzle-rate-limiter-middleware",
"description": "A rate limiter for Guzzle",
"keywords": [
"spatie",
"guzzle-rate-limiter-middleware"
],
"homepage": "https://github.com/spatie/guzzle-rate-limiter-middleware",
"license": "MIT",
"authors": [
{
"name": "Sebastian De Deyne",
"email": "sebastiandedeyne@gmail.com",
"homepage": "https://spatie.be",
"role": "Developer"
}
],
"require": {
"php": "^7.1|^8.0",
"guzzlehttp/guzzle": "^6.3|^7.0"
},
"require-dev": {
"larapack/dd": "^1.0",
"phpunit/phpunit": "^9.3.3"
},
"autoload": {
"psr-4": {
"Spatie\\GuzzleRateLimiterMiddleware\\": "src"
}
},
"autoload-dev": {
"psr-4": {
"Spatie\\GuzzleRateLimiterMiddleware\\Tests\\": "tests"
}
},
"scripts": {
"test": "vendor/bin/phpunit",
"test-coverage": "vendor/bin/phpunit --coverage-html coverage"
},
"config": {
"sort-packages": true
}
}
================================================
FILE: phpunit.xml.dist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="./vendor/phpunit/phpunit/phpunit.xsd"
bootstrap="vendor/autoload.php"
backupGlobals="false"
backupStaticAttributes="false"
colors="true"
verbose="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false">
<testsuites>
<testsuite name="Spatie Test Suite">
<directory>tests</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory suffix=".php">src/</directory>
</whitelist>
</filter>
<logging>
<log type="tap" target="build/report.tap"/>
<log type="junit" target="build/report.junit.xml"/>
<log type="coverage-html" target="build/coverage"/>
<log type="coverage-text" target="build/coverage.txt"/>
<log type="coverage-clover" target="build/logs/clover.xml"/>
</logging>
</phpunit>
================================================
FILE: src/Deferrer.php
================================================
<?php
namespace Spatie\GuzzleRateLimiterMiddleware;
interface Deferrer
{
public function getCurrentTime(): int;
public function sleep(int $milliseconds);
}
================================================
FILE: src/InMemoryStore.php
================================================
<?php
namespace Spatie\GuzzleRateLimiterMiddleware;
class InMemoryStore implements Store
{
/** @var int[] */
protected $timestamps = [];
public function get(): array
{
return $this->timestamps;
}
public function push(int $timestamp, int $limit)
{
$this->timestamps[] = $timestamp;
}
}
================================================
FILE: src/RateLimiter.php
================================================
<?php
namespace Spatie\GuzzleRateLimiterMiddleware;
class RateLimiter
{
const TIME_FRAME_MINUTE = 'minute';
const TIME_FRAME_SECOND = 'second';
/** @var int */
protected $limit;
/** @var string */
protected $timeFrame;
/** @var \Spatie\RateLimiter\Store */
protected $store;
/** @var \Spatie\GuzzleRateLimiterMiddleware\Deferrer */
protected $deferrer;
public function __construct(
int $limit,
string $timeFrame,
Store $store,
Deferrer $deferrer
) {
$this->limit = $limit;
$this->timeFrame = $timeFrame;
$this->store = $store;
$this->deferrer = $deferrer;
}
public function handle(callable $callback)
{
$delayUntilNextRequest = $this->delayUntilNextRequest();
if ($delayUntilNextRequest > 0) {
$this->deferrer->sleep($delayUntilNextRequest);
}
$this->store->push(
$this->deferrer->getCurrentTime(),
$this->limit
);
return $callback();
}
protected function delayUntilNextRequest(): int
{
$currentTimeFrameStart = $this->deferrer->getCurrentTime() - $this->timeFrameLengthInMilliseconds();
$requestsInCurrentTimeFrame = array_values(array_filter(
$this->store->get(),
function (int $timestamp) use ($currentTimeFrameStart) {
return $timestamp >= $currentTimeFrameStart;
}
));
if (count($requestsInCurrentTimeFrame) < $this->limit) {
return 0;
}
$oldestRequestStartTimeRelativeToCurrentTimeFrame =
$this->deferrer->getCurrentTime() - $requestsInCurrentTimeFrame[0];
return $this->timeFrameLengthInMilliseconds() - $oldestRequestStartTimeRelativeToCurrentTimeFrame;
}
protected function timeFrameLengthInMilliseconds(): int
{
if ($this->timeFrame === self::TIME_FRAME_MINUTE) {
return 60 * 1000;
}
return 1000;
}
}
================================================
FILE: src/RateLimiterMiddleware.php
================================================
<?php
namespace Spatie\GuzzleRateLimiterMiddleware;
use Psr\Http\Message\RequestInterface;
class RateLimiterMiddleware
{
/** @var \Spatie\GuzzleRateLimiterMiddleware\RateLimiter */
protected $rateLimiter;
private function __construct(RateLimiter $rateLimiter)
{
$this->rateLimiter = $rateLimiter;
}
public static function perSecond(int $limit, ?Store $store = null, ?Deferrer $deferrer = null): RateLimiterMiddleware
{
$rateLimiter = new RateLimiter(
$limit,
RateLimiter::TIME_FRAME_SECOND,
$store ?? new InMemoryStore(),
$deferrer ?? new SleepDeferrer()
);
return new static($rateLimiter);
}
public static function perMinute(int $limit, ?Store $store = null, ?Deferrer $deferrer = null): RateLimiterMiddleware
{
$rateLimiter = new RateLimiter(
$limit,
RateLimiter::TIME_FRAME_MINUTE,
$store ?? new InMemoryStore(),
$deferrer ?? new SleepDeferrer()
);
return new static($rateLimiter);
}
public function __invoke(callable $handler)
{
return function (RequestInterface $request, array $options) use ($handler) {
return $this->rateLimiter->handle(function () use ($request, $handler, $options) {
return $handler($request, $options);
});
};
}
}
================================================
FILE: src/SleepDeferrer.php
================================================
<?php
namespace Spatie\GuzzleRateLimiterMiddleware;
class SleepDeferrer implements Deferrer
{
public function getCurrentTime(): int
{
return (int) round(microtime(true) * 1000);
}
public function sleep(int $milliseconds)
{
usleep($milliseconds * 1000);
}
}
================================================
FILE: src/Store.php
================================================
<?php
namespace Spatie\GuzzleRateLimiterMiddleware;
interface Store
{
public function get(): array;
public function push(int $timestamp, int $limit);
}
================================================
FILE: tests/RateLimiterMiddlewareTest.php
================================================
<?php
namespace Spatie\GuzzleRateLimiterMiddleware\Tests;
use Spatie\GuzzleRateLimiterMiddleware\RateLimiterMiddleware;
class RateLimiterMiddlewareTest extends TestCase
{
/** @test */
public function it_has_named_constructors_to_create_instances()
{
$this->assertInstanceOf(
RateLimiterMiddleware::class,
RateLimiterMiddleware::perSecond(5)
);
$this->assertInstanceOf(
RateLimiterMiddleware::class,
RateLimiterMiddleware::perMinute(5)
);
}
}
================================================
FILE: tests/RateLimiterTest.php
================================================
<?php
namespace Spatie\GuzzleRateLimiterMiddleware\Tests;
use Spatie\GuzzleRateLimiterMiddleware\RateLimiter;
class RateLimiterTest extends TestCase
{
/** @test */
public function it_execute_actions_below_a_limit_in_seconds()
{
$rateLimiter = $this->createRateLimiter(3, RateLimiter::TIME_FRAME_SECOND);
$this->assertEquals(0, $this->deferrer->getCurrentTime());
$rateLimiter->handle(function () {
$this->deferrer->sleep(100);
});
$this->assertEquals(100, $this->deferrer->getCurrentTime());
$rateLimiter->handle(function () {
$this->deferrer->sleep(100);
});
$this->assertEquals(200, $this->deferrer->getCurrentTime());
$rateLimiter->handle(function () {
$this->deferrer->sleep(100);
});
$this->assertEquals(300, $this->deferrer->getCurrentTime());
$this->deferrer->sleep(700);
$rateLimiter->handle(function () {
$this->deferrer->sleep(100);
});
$this->assertEquals(1100, $this->deferrer->getCurrentTime());
$rateLimiter->handle(function () {
$this->deferrer->sleep(100);
});
$this->assertEquals(1200, $this->deferrer->getCurrentTime());
}
/** @test */
public function it_defers_actions_when_it_reaches_a_limit_in_seconds()
{
$rateLimiter = $this->createRateLimiter(3, RateLimiter::TIME_FRAME_SECOND);
$this->assertEquals(0, $this->deferrer->getCurrentTime());
$rateLimiter->handle(function () {
});
$this->assertEquals(0, $this->deferrer->getCurrentTime());
$rateLimiter->handle(function () {
});
$this->assertEquals(0, $this->deferrer->getCurrentTime());
$rateLimiter->handle(function () {
});
$this->assertEquals(0, $this->deferrer->getCurrentTime());
$rateLimiter->handle(function () {
});
$this->assertEquals(1000, $this->deferrer->getCurrentTime());
}
/** @test */
public function it_execute_actions_below_a_limit_in_minutes()
{
$rateLimiter = $this->createRateLimiter(3, RateLimiter::TIME_FRAME_MINUTE);
$this->assertEquals(0, $this->deferrer->getCurrentTime());
$rateLimiter->handle(function () {
$this->deferrer->sleep(100);
});
$this->assertEquals(100, $this->deferrer->getCurrentTime());
$rateLimiter->handle(function () {
$this->deferrer->sleep(100);
});
$this->assertEquals(200, $this->deferrer->getCurrentTime());
$rateLimiter->handle(function () {
$this->deferrer->sleep(100);
});
$this->assertEquals(300, $this->deferrer->getCurrentTime());
$this->deferrer->sleep(59700);
$rateLimiter->handle(function () {
$this->deferrer->sleep(100);
});
$this->assertEquals(60100, $this->deferrer->getCurrentTime());
}
/** @test */
public function it_defers_actions_when_it_reaches_a_limit_in_minutes()
{
$rateLimiter = $this->createRateLimiter(3, RateLimiter::TIME_FRAME_MINUTE);
$this->assertEquals(0, $this->deferrer->getCurrentTime());
$rateLimiter->handle(function () {
});
$this->assertEquals(0, $this->deferrer->getCurrentTime());
$rateLimiter->handle(function () {
});
$this->assertEquals(0, $this->deferrer->getCurrentTime());
$rateLimiter->handle(function () {
});
$this->assertEquals(0, $this->deferrer->getCurrentTime());
$rateLimiter->handle(function () {
});
$this->assertEquals(60000, $this->deferrer->getCurrentTime());
}
}
================================================
FILE: tests/TestCase.php
================================================
<?php
namespace Spatie\GuzzleRateLimiterMiddleware\Tests;
use PHPUnit\Framework\TestCase as BaseTestCase;
use Spatie\GuzzleRateLimiterMiddleware\InMemoryStore;
use Spatie\GuzzleRateLimiterMiddleware\RateLimiter;
abstract class TestCase extends BaseTestCase
{
/** @var \Spatie\GuzzleRateLimiterMiddleware\Tests\TestDeferrer */
protected $deferrer;
protected function setUp(): void
{
parent::setUp();
$this->deferrer = new TestDeferrer();
}
public function createRateLimiter(int $limit, string $timeFrame): RateLimiter
{
return new RateLimiter($limit, $timeFrame, new InMemoryStore(), $this->deferrer);
}
}
================================================
FILE: tests/TestDeferrer.php
================================================
<?php
namespace Spatie\GuzzleRateLimiterMiddleware\Tests;
use Spatie\GuzzleRateLimiterMiddleware\Deferrer;
class TestDeferrer implements Deferrer
{
/** @var int */
protected $currentTime = 0;
public function getCurrentTime(): int
{
return $this->currentTime;
}
public function sleep(int $milliseconds)
{
$this->currentTime += $milliseconds;
}
}
gitextract_wrtnnr9r/
├── .editorconfig
├── .gitattributes
├── .gitignore
├── .scrutinizer.yml
├── .styleci.yml
├── .travis.yml
├── CHANGELOG.md
├── LICENSE.md
├── README.md
├── composer.json
├── phpunit.xml.dist
├── src/
│ ├── Deferrer.php
│ ├── InMemoryStore.php
│ ├── RateLimiter.php
│ ├── RateLimiterMiddleware.php
│ ├── SleepDeferrer.php
│ └── Store.php
└── tests/
├── RateLimiterMiddlewareTest.php
├── RateLimiterTest.php
├── TestCase.php
└── TestDeferrer.php
SYMBOL INDEX (35 symbols across 10 files)
FILE: src/Deferrer.php
type Deferrer (line 5) | interface Deferrer
method getCurrentTime (line 7) | public function getCurrentTime(): int;
method sleep (line 9) | public function sleep(int $milliseconds);
FILE: src/InMemoryStore.php
class InMemoryStore (line 5) | class InMemoryStore implements Store
method get (line 10) | public function get(): array
method push (line 15) | public function push(int $timestamp, int $limit)
FILE: src/RateLimiter.php
class RateLimiter (line 5) | class RateLimiter
method __construct (line 22) | public function __construct(
method handle (line 34) | public function handle(callable $callback)
method delayUntilNextRequest (line 50) | protected function delayUntilNextRequest(): int
method timeFrameLengthInMilliseconds (line 71) | protected function timeFrameLengthInMilliseconds(): int
FILE: src/RateLimiterMiddleware.php
class RateLimiterMiddleware (line 7) | class RateLimiterMiddleware
method __construct (line 12) | private function __construct(RateLimiter $rateLimiter)
method perSecond (line 17) | public static function perSecond(int $limit, ?Store $store = null, ?De...
method perMinute (line 29) | public static function perMinute(int $limit, ?Store $store = null, ?De...
method __invoke (line 41) | public function __invoke(callable $handler)
FILE: src/SleepDeferrer.php
class SleepDeferrer (line 5) | class SleepDeferrer implements Deferrer
method getCurrentTime (line 7) | public function getCurrentTime(): int
method sleep (line 12) | public function sleep(int $milliseconds)
FILE: src/Store.php
type Store (line 5) | interface Store
method get (line 7) | public function get(): array;
method push (line 9) | public function push(int $timestamp, int $limit);
FILE: tests/RateLimiterMiddlewareTest.php
class RateLimiterMiddlewareTest (line 7) | class RateLimiterMiddlewareTest extends TestCase
method it_has_named_constructors_to_create_instances (line 10) | public function it_has_named_constructors_to_create_instances()
FILE: tests/RateLimiterTest.php
class RateLimiterTest (line 7) | class RateLimiterTest extends TestCase
method it_execute_actions_below_a_limit_in_seconds (line 10) | public function it_execute_actions_below_a_limit_in_seconds()
method it_defers_actions_when_it_reaches_a_limit_in_seconds (line 50) | public function it_defers_actions_when_it_reaches_a_limit_in_seconds()
method it_execute_actions_below_a_limit_in_minutes (line 78) | public function it_execute_actions_below_a_limit_in_minutes()
method it_defers_actions_when_it_reaches_a_limit_in_minutes (line 112) | public function it_defers_actions_when_it_reaches_a_limit_in_minutes()
FILE: tests/TestCase.php
class TestCase (line 9) | abstract class TestCase extends BaseTestCase
method setUp (line 14) | protected function setUp(): void
method createRateLimiter (line 21) | public function createRateLimiter(int $limit, string $timeFrame): Rate...
FILE: tests/TestDeferrer.php
class TestDeferrer (line 7) | class TestDeferrer implements Deferrer
method getCurrentTime (line 12) | public function getCurrentTime(): int
method sleep (line 17) | public function sleep(int $milliseconds)
Condensed preview — 21 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (22K chars).
[
{
"path": ".editorconfig",
"chars": 313,
"preview": "; This file is for unifying the coding style for different editors and IDEs.\n; More information at https://editorconfig."
},
{
"path": ".gitattributes",
"chars": 395,
"preview": "# Path-based git attributes\n# https://www.kernel.org/pub/software/scm/git/docs/gitattributes.html\n\n# Ignore all test and"
},
{
"path": ".gitignore",
"chars": 63,
"preview": "build\ncomposer.lock\ndocs\nvendor\ncoverage\n.phpunit.result.cache\n"
},
{
"path": ".scrutinizer.yml",
"chars": 507,
"preview": "filter:\n excluded_paths: [tests/*]\n\nchecks:\n php:\n remove_extra_empty_lines: true\n remove_php_closin"
},
{
"path": ".styleci.yml",
"chars": 66,
"preview": "preset: laravel\n\ndisabled:\n - single_class_element_per_statement\n"
},
{
"path": ".travis.yml",
"chars": 481,
"preview": "language: php\n\nphp:\n - 7.1\n - 7.2\n - 7.3\n - 8.0\n - 8.1\n - 8.2\n - 8.3\n - 8.4\n\nenv:\n matrix:\n - COMPOSER_FLAGS"
},
{
"path": "CHANGELOG.md",
"chars": 639,
"preview": "# Changelog\n\nAll notable changes to `guzzle-rate-limiter-middleware` will be documented in this file\n\n## 2.0.1 - 2020-12"
},
{
"path": "LICENSE.md",
"chars": 1090,
"preview": "The MIT License (MIT)\n\nCopyright (c) Spatie bvba <info@spatie.be>\n\nPermission is hereby granted, free of charge, to any "
},
{
"path": "README.md",
"chars": 4760,
"preview": "# A rate limiter middleware for Guzzle\n\n[: int;\n\n "
},
{
"path": "src/InMemoryStore.php",
"chars": 337,
"preview": "<?php\n\nnamespace Spatie\\GuzzleRateLimiterMiddleware;\n\nclass InMemoryStore implements Store\n{\n /** @var int[] */\n p"
},
{
"path": "src/RateLimiter.php",
"chars": 2033,
"preview": "<?php\n\nnamespace Spatie\\GuzzleRateLimiterMiddleware;\n\nclass RateLimiter\n{\n const TIME_FRAME_MINUTE = 'minute';\n co"
},
{
"path": "src/RateLimiterMiddleware.php",
"chars": 1414,
"preview": "<?php\n\nnamespace Spatie\\GuzzleRateLimiterMiddleware;\n\nuse Psr\\Http\\Message\\RequestInterface;\n\nclass RateLimiterMiddlewar"
},
{
"path": "src/SleepDeferrer.php",
"chars": 300,
"preview": "<?php\n\nnamespace Spatie\\GuzzleRateLimiterMiddleware;\n\nclass SleepDeferrer implements Deferrer\n{\n public function getC"
},
{
"path": "src/Store.php",
"chars": 163,
"preview": "<?php\n\nnamespace Spatie\\GuzzleRateLimiterMiddleware;\n\ninterface Store\n{\n public function get(): array;\n\n public fu"
},
{
"path": "tests/RateLimiterMiddlewareTest.php",
"chars": 542,
"preview": "<?php\n\nnamespace Spatie\\GuzzleRateLimiterMiddleware\\Tests;\n\nuse Spatie\\GuzzleRateLimiterMiddleware\\RateLimiterMiddleware"
},
{
"path": "tests/RateLimiterTest.php",
"chars": 3749,
"preview": "<?php\n\nnamespace Spatie\\GuzzleRateLimiterMiddleware\\Tests;\n\nuse Spatie\\GuzzleRateLimiterMiddleware\\RateLimiter;\n\nclass R"
},
{
"path": "tests/TestCase.php",
"chars": 667,
"preview": "<?php\n\nnamespace Spatie\\GuzzleRateLimiterMiddleware\\Tests;\n\nuse PHPUnit\\Framework\\TestCase as BaseTestCase;\nuse Spatie\\G"
},
{
"path": "tests/TestDeferrer.php",
"chars": 398,
"preview": "<?php\n\nnamespace Spatie\\GuzzleRateLimiterMiddleware\\Tests;\n\nuse Spatie\\GuzzleRateLimiterMiddleware\\Deferrer;\n\nclass Test"
}
]
About this extraction
This page contains the full source code of the spatie/guzzle-rate-limiter-middleware GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 21 files (19.9 KB), approximately 5.5k tokens, and a symbol index with 35 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.