1 回答
TA贡献1865条经验 获得超7个赞
从同一文档页面:
您也可以将此功能与动态速率限制结合使用。例如,如果您的User模型包含一个rate_limit属性,您可以将属性的名称传递给throttle中间件,以便用于计算经过身份验证的用户的最大请求数
因此,鉴于上述情况,您可以在模型上添加一个访问器User,该访问器根据他们当前的订阅计划获取速率限制值:
class User extends Authenticatable
{
public function getRateLimitAttribute()
{
// Get license if it's a model
if ($license === 'basic') {
return 10000;
}
// Return some default here
}
}
然后,您可以像这样使用动态速率限制值:
Route::middleware('auth:api', 'throttle:rate_limit,1')->group(function () {
// Rate-limited routes
});
至于每月限额,您需要在某处保留一个柜台,并在每个请求时检查。您可以在另一个中间件中记录每个 API 请求:
class LogRequest
{
public function handle($request, Closure $next)
{
return $next($request);
}
public function terminate($request, $response)
{
LogRequestJob::dispatch($request);
}
}
class LogRequestJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public function __construct(Request $request)
{
$this->request = $request;
}
public function handle()
{
// Insert row for user to log request
RequestLog::create([
'user_id' => $this->request->user()->getKey(),
'path' => $this->request->path(),
// Store any other request data you're interested in
]);
}
}
然后,您需要在处理请求之前检查计数,再次使用中间件:
use Symfony\Component\HttpKernel\Exception\TooManyRequestsHttpException;
class CheckRequestInLimit
{
public function handle($request, Closure $next)
{
$year = Carbon::now()->year;
$month = Carbon::now()->month;
$count = RequestLog::user($request->user())->year($year)->month($month)->count();
$limit = $request->user()->monthly_limit; // another accessor
if ($count < $limit) {
return $next($request);
}
// Count is equal to (or greater than) limit; throw exception
$retryAfter = Carbon::today()->addMonth()->startOfMonth();
$message = 'You have exceeded your monthly limit';
throw new TooManyRequestsHttpException($retryAfter, $message);
}
}
希望这能让您深思!
2021 年 11 月 1 日编辑:此答案是针对旧版本的 Laravel 编写的。Laravel 后来引入了速率限制,这将为上述问题提供更简洁的解决方案:
RateLimiter::for('api', function (Request $request) {
return [
Limit::perHour(60)->by($request->user()->getKey()),
Limit::perDay(10000, 30)->by($request->user()->getKey()),
];
});
- 1 回答
- 0 关注
- 101 浏览
添加回答
举报