Skip to content

Commit

Permalink
update namespace and minimum php to 8.1 (#13)
Browse files Browse the repository at this point in the history
  • Loading branch information
Lansoweb authored Oct 30, 2023
1 parent f05ede5 commit 81a0697
Show file tree
Hide file tree
Showing 12 changed files with 72 additions and 105 deletions.
20 changes: 0 additions & 20 deletions .php_cs

This file was deleted.

12 changes: 7 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Attention! This middleware does not validate the Api Key, you must add a middlew

## Requirements

* PHP >= 7.4
* PHP >= 8.0
* Psr\SimpleCache implementation

## Installation
Expand All @@ -23,7 +23,8 @@ composer require los/los-rate-limit

### Configuration
```php
'los_rate_limit' => [
'los' => [
'rate-limit' => [
'max_requests' => 100,
'reset_time' => 3600,
'ip_max_requests' => 100,
Expand Down Expand Up @@ -59,7 +60,8 @@ composer require los/los-rate-limit
],
'hash_ips' => false,
'hash_salt' => 'Los%Rate',
]
],
],
```

* `max_requests` How many requests are allowed before the reset time (using API Key)
Expand Down Expand Up @@ -91,8 +93,8 @@ The provided factory uses the container to get a \Psr\SimpleCache\CacheInterface
Most implementations provide both PSR-6 and PSR-16, or at least a decorator.
Recommended: [zend-cache](https://github.com/laminas/laminas-cache) or [symfony/cache](https://github.com/symfony/cache).

### Zend Expressive
### Laminas / Mezzio

If you are using [expressive-skeleton](https://github.com/mezzio/mezzio-skeleton),
If you are using [mezzio-skeleton](https://github.com/mezzio/mezzio-skeleton),
you can copy `config/los-rate-limit.local.php.dist` to
`config/autoload/los-rate-limit.local.php` and modify configuration as your needs.
22 changes: 12 additions & 10 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,18 @@
"name": "los/los-rate-limit",
"description": "Rate Limit Middleware for PHP",
"require": {
"php": "^7.4 || ^8.0",
"php": "^8.1",
"psr/http-message": "^1.0",
"psr/container": "^1.0",
"psr/container": "^2.0",
"psr/http-server-middleware": "^1.0",
"mezzio/mezzio-problem-details": "^1.0",
"laminas/laminas-diactoros": "^1.8.6 || ^2.0",
"psr/simple-cache": "^1.0"
"laminas/laminas-diactoros": "^2.0",
"psr/simple-cache": "^3.0"
},
"require-dev": {
"doctrine/coding-standard": "^9.0",
"doctrine/coding-standard": "^11.0",
"php-coveralls/php-coveralls": "^2.1",
"phpstan/phpstan": "^1.2",
"phpunit/php-token-stream": "^4.0.4",
"phpunit/phpunit": "^9.0",
"squizlabs/php_codesniffer": "^3.4"
},
Expand All @@ -27,17 +26,20 @@
],
"autoload-dev": {
"psr-4": {
"LosMiddlewareTest\\RateLimit\\": "test/"
"LosTest\\RateLimit\\": "test/"
}
},
"autoload": {
"psr-4": {
"LosMiddleware\\RateLimit\\": "src/"
"Los\\RateLimit\\": "src/"
}
},
"type": "library",
"config": {
"sort-packages": true
"sort-packages": true,
"allow-plugins": {
"dealerdirect/phpcodesniffer-composer-installer": true
}
},
"support": {
"email": "leandro@leandrosilva.info",
Expand All @@ -58,7 +60,7 @@
],
"cs-check": "phpcs",
"cs-fix": "phpcbf",
"phpstan": "phpstan analyse -l max -c phpstan.neon src",
"phpstan": "phpstan analyse",
"test": "phpunit --colors=always",
"test-coverage": "phpunit --colors=always --coverage-clover clover.xml",
"upload-coverage": "php-coveralls -v"
Expand Down
27 changes: 14 additions & 13 deletions config/los-rate-limit.local.php.dist
Original file line number Diff line number Diff line change
@@ -1,23 +1,24 @@
<?php

return [
'los_rate_limit' => [
'max_requests' => 100,
'reset_time' => 3600,
'ip_max_requests' => 100,
'ip_reset_time' => 3600,
'api_header' => 'X-Api-Key',
'trust_forwarded' => false,
'headers' => [
'limit' => 'X-RateLimit-Limit',
'remaining' => 'X-RateLimit-Remaining',
'reset' => 'X-RateLimit-Reset',
'los' => [
'rate-limit' => [
'max_requests' => 100,
'reset_time' => 3600,
'ip_max_requests' => 100,
'ip_reset_time' => 3600,
'api_header' => 'X-Api-Key',
'trust_forwarded' => false,
'headers' => [
'limit' => 'X-RateLimit-Limit',
'remaining' => 'X-RateLimit-Remaining',
'reset' => 'X-RateLimit-Reset',
],
],
],
'dependencies' => [
'factories' => [
LosMiddleware\RateLimit\RateLimitMiddleware::class =>
LosMiddleware\RateLimit\RateLimitMiddlewareFactory::class,
Los\RateLimit\RateLimitMiddleware::class => Los\RateLimit\RateLimitMiddlewareFactory::class,
],
],
];
4 changes: 1 addition & 3 deletions phpcs.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,5 @@
<file>config</file>
<file>src</file>

<rule ref="Doctrine">
<exclude name="SlevomatCodingStandard.TypeHints.TypeHintDeclaration" />
</rule>
<rule ref="Doctrine"/>
</ruleset>
3 changes: 3 additions & 0 deletions phpstan.neon
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
parameters:
level: 4
paths:
- ./src
2 changes: 1 addition & 1 deletion src/Exception/InvalidArgument.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

declare(strict_types=1);

namespace LosMiddleware\RateLimit\Exception;
namespace Los\RateLimit\Exception;

class InvalidArgument extends ReachedRateLimit
{
Expand Down
2 changes: 1 addition & 1 deletion src/Exception/MissingRequirement.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

declare(strict_types=1);

namespace LosMiddleware\RateLimit\Exception;
namespace Los\RateLimit\Exception;

class MissingRequirement extends ReachedRateLimit
{
Expand Down
5 changes: 3 additions & 2 deletions src/Exception/ReachedRateLimit.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,19 @@

declare(strict_types=1);

namespace LosMiddleware\RateLimit\Exception;
namespace Los\RateLimit\Exception;

use Exception;
use Mezzio\ProblemDetails\Exception\CommonProblemDetailsExceptionTrait;
use Mezzio\ProblemDetails\Exception\ProblemDetailsExceptionInterface;

use function sprintf;

class ReachedRateLimit extends Exception implements ProblemDetailsExceptionInterface
{
use CommonProblemDetailsExceptionTrait;

public static function create(int $maxRequests) : self
public static function create(int $maxRequests): self
{
$message = sprintf('You have exceeded your %d requests rate limit', $maxRequests);
$e = new self($message);
Expand Down
47 changes: 15 additions & 32 deletions src/RateLimitMiddleware.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,18 @@

declare(strict_types=1);

namespace LosMiddleware\RateLimit;
namespace Los\RateLimit;

use LogicException;
use LosMiddleware\RateLimit\Exception\MissingRequirement;
use LosMiddleware\RateLimit\Exception\ReachedRateLimit;
use Los\RateLimit\Exception\MissingRequirement;
use Los\RateLimit\Exception\ReachedRateLimit;
use Mezzio\ProblemDetails\ProblemDetailsResponseFactory;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Psr\SimpleCache\CacheInterface;
use Mezzio\ProblemDetails\ProblemDetailsResponseFactory;
use const FILTER_VALIDATE_IP;

use function array_key_exists;
use function array_map;
use function array_slice;
Expand All @@ -25,36 +25,25 @@
use function str_replace;
use function time;

use const FILTER_VALIDATE_IP;

class RateLimitMiddleware implements MiddlewareInterface
{
public const HEADER_LIMIT = 'X-RateLimit-Limit';
public const HEADER_RESET = 'X-RateLimit-Reset';
public const HEADER_REMAINING = 'X-RateLimit-Remaining';

/** @var CacheInterface */
private $storage;

/** @var RateLimitOptions */
protected $options;

/** @var ProblemDetailsResponseFactory */
private $problemResponseFactory;

public function __construct(
CacheInterface $storage,
ProblemDetailsResponseFactory $problemResponseFactory,
RateLimitOptions $options
private CacheInterface $storage,
private ProblemDetailsResponseFactory $problemResponseFactory,
protected RateLimitOptions $options,
) {
$this->storage = $storage;
$this->problemResponseFactory = $problemResponseFactory;
$this->options = $options;

if ($this->options['prefer_forwarded'] && ! $this->options['trust_forwarded']) {
throw new LogicException('You must also "trust_forwarded" headers to "prefer_forwarded" ones.');
}
}

public function process(ServerRequestInterface $request, RequestHandlerInterface $handler) : ResponseInterface
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
$keyArray = $request->getHeader($this->options['api_header']);

Expand Down Expand Up @@ -119,7 +108,7 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface
if ($remaining === 0) {
$response = $this->problemResponseFactory->createResponseFromThrowable(
$request,
ReachedRateLimit::create($maxRequests)
ReachedRateLimit::create($maxRequests),
);
} else {
$response = $handler->handle($request);
Expand All @@ -132,10 +121,7 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface
return $response;
}

/**
* @return mixed|null
*/
private function getClientIp(ServerRequestInterface $request)
private function getClientIp(ServerRequestInterface $request): string|null
{
$server = $request->getServerParams();
$ips = [];
Expand Down Expand Up @@ -178,17 +164,14 @@ private function getClientIp(ServerRequestInterface $request)
return null;
}

private function hashIp(string $ip) : string
private function hashIp(string $ip): string
{
$salt = $this->options['hash_salt'];

return md5($salt . $ip);
}

/**
* @param mixed $possibleIp
*/
private function isIp($possibleIp) : bool
private function isIp(mixed $possibleIp): bool
{
return filter_var($possibleIp, FILTER_VALIDATE_IP) !== false;
}
Expand Down
10 changes: 5 additions & 5 deletions src/RateLimitMiddlewareFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,23 @@

declare(strict_types=1);

namespace LosMiddleware\RateLimit;
namespace Los\RateLimit;

use Mezzio\ProblemDetails\ProblemDetailsResponseFactory;
use Psr\Container\ContainerInterface;
use Psr\SimpleCache\CacheInterface;
use Mezzio\ProblemDetails\ProblemDetailsResponseFactory;

class RateLimitMiddlewareFactory
{
public function __invoke(ContainerInterface $container) : RateLimitMiddleware
public function __invoke(ContainerInterface $container): RateLimitMiddleware
{
$config = $container->get('config');
$rateConfig = $config['los_rate_limit'] ?? [];
$rateConfig = $config['los']['rate-limit'] ?? $config['los_rate_limit'] ?? [];

return new RateLimitMiddleware(
$container->get(CacheInterface::class),
$container->get(ProblemDetailsResponseFactory::class),
new RateLimitOptions($rateConfig)
new RateLimitOptions($rateConfig),
);
}
}
23 changes: 10 additions & 13 deletions src/RateLimitOptions.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,17 @@

declare(strict_types=1);

namespace LosMiddleware\RateLimit;
namespace Los\RateLimit;

use ArrayObject;
use ReturnTypeWillChange;

use function array_key_exists;

class RateLimitOptions extends ArrayObject
{
/** @var array */
private $defaultValues = [
// phpcs:ignore
private array $defaultValues = [
'max_requests' => 100,
'reset_time' => 3600,
'ip_max_requests' => 100,
Expand Down Expand Up @@ -38,18 +40,13 @@ class RateLimitOptions extends ArrayObject
'hash_salt' => 'Los%Rate',
];

/**
* @param string $index
*
* @return mixed|null
*/
#[\ReturnTypeWillChange]
public function offsetGet($index)
#[ReturnTypeWillChange]
public function offsetGet(mixed $key): mixed
{
if (! $this->offsetExists($index) && array_key_exists($index, $this->defaultValues)) {
return $this->defaultValues[$index];
if (! $this->offsetExists($key) && array_key_exists($key, $this->defaultValues)) {
return $this->defaultValues[$key];
}

return parent::offsetGet($index);
return parent::offsetGet($key);
}
}

0 comments on commit 81a0697

Please sign in to comment.