Laravel Spark - Могу ли я ограничить количество вызовов API плана в месяц и количество вызовов API в минуту / час? - PullRequest
2 голосов
/ 08 января 2020

Я хочу использовать Laravel Spark для создания различных лицензий для API. Я хочу ограничить количество вызовов API в месяц, а также в час / минуту. Например, лицензия Basi c будет разрешать 10 000 ежемесячных вызовов API, но я также хочу ограничить количество вызовов API в час / минуту для той же учетной записи. Можно ли это сделать с помощью laravel spark?

Существует: throttle и rate_limit, но можно ли ограничить общее количество вызовов API в месяц, а также в час / минуту? Например: всего 10 000 вызовов API в месяц и максимум 60 вызовов API в час / минуту?

В соответствии с документами, я могу ограничить доступ в минуту / час: https://laravel.com/docs/6.x/routing#rate -ограничение

Что-то вроде этого сочетает газ с ограничением скорости:

Route::middleware('auth:api', 'throttle:10|rate_limit,1')->group(function () {     
Route::get('/user', function () { // }); 
});

Но мой главный вопрос - как мне объединить ограничение скорости в минуту / час с месячным лимитом?

Ответы [ 2 ]

1 голос
/ 08 января 2020

На той же странице документации:

Вы также можете комбинировать эту функцию с Dynami c Ограничения скорости . Например, если ваша модель 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
    }
}

Вы можете затем используйте динамическое предельное значение c, например:

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);
    }
}

Надеемся это дает пищу для размышлений!

0 голосов
/ 08 января 2020

Создайте промежуточное ПО и проверьте там, когда был сделан последний запрос API.

...