Pas*_*cut 2 php throttling laravel
我想使用 Laravel Spark 为 API 创建不同的许可证。我想限制每月以及每小时/分钟的 API 调用。例如,基本许可证允许每月 10 000 次 API 调用,但我还想限制同一帐户每小时/分钟的 API 调用。这可以用 laravel Spark 来完成吗?
有:throttle 和rate_limit,但是我可以限制每月以及每小时/分钟的API 调用总数吗?例如:每月总共 10 000 次 api 调用,每小时/分钟最多 60 次 api 调用?
根据文档,我可以限制每分钟/小时的访问:https://laravel.com/docs/6.x/routing#rate-limiting
像这样的东西结合了节流和速率限制:
Route::middleware('auth:api', 'throttle:10|rate_limit,1')->group(function () {
Route::get('/user', function () { // });
});
Run Code Online (Sandbox Code Playgroud)
但我的主要问题是如何将每分钟/小时的速率限制与每月限制结合起来?
来自同一文档页面:
\n\n\n\n您还可以将此功能与动态速率限制结合起来。例如,如果您的
\nUser模型包含一个rate_limit属性,您可以将该属性的名称传递给throttle中间件,以便使用它来计算经过身份验证的用户的最大请求计数
因此,鉴于上述情况,您可以在模型上添加一个访问器User,该访问器根据当前的订阅计划获取速率限制值:
class User extends Authenticatable\n{\n public function getRateLimitAttribute()\n {\n // Get license if it\'s a model\n\n if ($license === \'basic\') {\n return 10000;\n }\n\n // Return some default here\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n然后,您可以像这样使用动态速率限制值:
\nRoute::middleware(\'auth:api\', \'throttle:rate_limit,1\')->group(function () {\n // Rate-limited routes\n});\nRun Code Online (Sandbox Code Playgroud)\n至于每月限制,您\xe2\x80\x99需要在某处保留一个计数器,并在每个请求时检查该计数器。您可以在另一个中间件中记录每个 API 请求:
\nclass LogRequest\n{\n public function handle($request, Closure $next)\n {\n return $next($request);\n }\n\n public function terminate($request, $response)\n {\n LogRequestJob::dispatch($request);\n }\n}\nRun Code Online (Sandbox Code Playgroud)\nclass LogRequestJob implements ShouldQueue\n{\n use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;\n\n public function __construct(Request $request)\n {\n $this->request = $request;\n }\n\n public function handle()\n {\n // Insert row for user to log request\n RequestLog::create([\n \'user_id\' => $this->request->user()->getKey(),\n \'path\' => $this->request->path(),\n // Store any other request data you\'re interested in\n ]);\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n然后,您\xe2\x80\x99ll需要在处理请求之前检查计数,再次使用中间件:
\nuse Symfony\\Component\\HttpKernel\\Exception\\TooManyRequestsHttpException;\n\nclass CheckRequestInLimit\n{\n public function handle($request, Closure $next)\n {\n $year = Carbon::now()->year;\n $month = Carbon::now()->month;\n $count = RequestLog::user($request->user())->year($year)->month($month)->count();\n $limit = $request->user()->monthly_limit; // another accessor\n\n if ($count < $limit) {\n return $next($request);\n }\n\n // Count is equal to (or greater than) limit; throw exception\n $retryAfter = Carbon::today()->addMonth()->startOfMonth();\n $message = \'You have exceeded your monthly limit\';\n\n throw new TooManyRequestsHttpException($retryAfter, $message);\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n希望这能给您带来思考!
\n2021 年 11 月 1 日编辑:这个答案是针对旧版本的 Laravel 编写的。Laravel 后来引入了速率限制,这将为上述问题提供更简洁的解决方案:
\nRateLimiter::for(\'api\', function (Request $request) {\n return [\n Limit::perHour(60)->by($request->user()->getKey()),\n Limit::perDay(10000, 30)->by($request->user()->getKey()),\n ];\n});\nRun Code Online (Sandbox Code Playgroud)\n