nikolaposa/rate-limit-middleware

PSR-15 中间件,用于限制 API 或其他应用程序端点的请求频率。

2.0.0 2021-10-31 11:27 UTC

This package is auto-updated.

Last update: 2024-08-29 05:29:11 UTC


README

Build Status Scrutinizer Code Quality Code Coverage Latest Stable Version PDS Skeleton

PSR-15 中间件,用于限制 API 或其他应用程序端点的请求频率。它建立在通用的 速率限制器 之上。

安装

推荐通过 Composer 安装。运行以下命令安装最新版本的包并将其添加到项目的 composer.json

composer require nikolaposa/rate-limit-middleware

使用方法

Rate Limit 中间件设计为按路由使用,以便您可以为每个单独的端点或一组端点设置请求频率限制策略。这是通过称为 管道 的中间件组合机制实现的。

完整示例

以下示例演示了如何在基于 Mezzio 的应用程序中使用 RateLimitMiddleware,但相同的原理适用于任何中间件框架。

dependencies.php

use Laminas\Diactoros\Response\JsonResponse;
use Psr\Container\ContainerInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
use RateLimit\Middleware\RateLimitMiddleware;
use RateLimit\Middleware\ResolveIpAddressAsUserIdentity;
use RateLimit\Middleware\ResolveUserIdentity;
use RateLimit\Rate;
use RateLimit\RateLimiter;
use RateLimit\RedisRateLimiter;

return [
    'dependencies' => [
        'invokables' => [
            ResolveUserIdentity::class => ResolveIpAddressAsUserIdentity::class,
        ],
        'factories'  => [
            'RateLimit\\Strategy\\Api' => function (ContainerInterface $container) {
                return new RedisRateLimiter(Rate::perSecond(5), $container->get(Redis::class), 'rate_limit:api:');
            },
            'RateLimit\\Strategy\\CreatePost' => function (ContainerInterface $container) {
                return new RedisRateLimiter(Rate::perDay(20), $container->get(Redis::class), 'rate_limit:web:post');
            },
            // default limit exceeded handler; anonymous class is used only for the sake 
            // of simplicity of the example
            'RateLimit\\LimitExceededRequestHandler' => function () {
                return new class implements RequestHandlerInterface {
                    public function handle(ServerRequestInterface $request): ResponseInterface
                    {
                        return new JsonResponse(['error' => 'Too many requests']);
                    }
                };
            },
            // rate limit middleware for different endpoints
            'RateLimit\\ApiRateLimitMiddleware' => function (ContainerInterface $container) {
                return new RateLimitMiddleware(
                   $container->get('RateLimiter\\Strategy\\Api'),
                   'api',
                   $container->get(ResolveUserIdentity::class),
                   $container->get('RateLimit\\LimitExceededRequestHandler')
               );
            },
            'RateLimit\\CreatePostRateLimitMiddleware' => function (ContainerInterface $container) {
                return new RateLimitMiddleware(
                   $container->get('RateLimiter\\Strategy\\CreatePost'),
                   'post.create',
                   $container->get(ResolveUserIdentity::class),
                   $container->get('RateLimit\\LimitExceededRequestHandler')
               );
            },
        ],
    ],
];

index.php

$app->get('/', App\Handler\HomePageHandler::class, 'home');

$app->get('/posts', [
    App\Handler\ListPostsHandler::class,
], 'post.list');
$app->post('/posts', [
    'RateLimit\\CreatePostRateLimitMiddleware',
    App\Handler\CreatePostHandler::class,
], 'post.create');
$app->put('/posts/:id', App\Handler\UpdatePostHandler::class, 'post.edit');

$app->route('/api/resource[/{id:[a-f0-9]{32}}]', [
    AuthenticationMiddleware::class,
    'RateLimit\\ApiRateLimitMiddleware',
    ApiResource::class,
], ['GET', 'POST', 'PATCH', 'DELETE'], 'api-resource');

致谢

许可证

在 MIT 许可证下发布 - 详细信息请参阅许可证文件