Laravel :API 请求频率限制(Throttle中间件),自定义返回JSON类型,自定义时间单位

in Default with 0 comment

Laravel (Throttle中间件)

Laravel 自带了一个 Throttle 中间件,默认的设置是 1 分钟内请求超过 60 次就会触发这个,然后服务器就会返回 429 Too Many Requests

这个默认配置可以在 app\Http\Kernel.php 中看到

QQ截图20191007154542.png

限流原理

更多参考文档:https://www.cnblogs.com/toughlife/p/10601069.html

自定义返回的类型

Laravel 默认 返回的是一个 429html 页面,做 api 的话这样不太好
我们新建一个中间件,来替换掉原来的中间件

artisan 命令新建一个中间件:php artisan make:middleware ThrottleRequests

编写代码:

继承原来的ThrottleRequests ,稍微修改一下就可以了。

如果限制时间要修改成秒的话, 请查看 :$this->limiter->hit($key,&decayMinutes * 60)

$decayMinutes * 60 ,如果 decayMinutes = 1 的话, 那么就是限制一分钟, 1*60

那么修改成 $this->limiter->hit($key,&decayMinutes),就成限制秒了

<?php

namespace App\Http\Middleware;


use Closure;
use Illuminate\Http\Response;

class ThrottleRequests extends \Illuminate\Routing\Middleware\ThrottleRequests
{


    public function handle($request, Closure $next, $maxAttempts = 60, $decayMinutes = 1)
    {
        $key = $this->resolveRequestSignature($request);

        $maxAttempts = $this->resolveMaxAttempts($request, $maxAttempts);

        if ($this->limiter->tooManyAttempts($key, $maxAttempts)) {
            return $this->buildException($key, $maxAttempts);
          //throw $this->buildException($key, $maxAttempts);
         // 原来的是抛出异常,修改成直接返回
        }
       //去掉 `* 60` 限制秒级,加上去限制分钟,要限制其他单位,可以自己算的
        $this->limiter->hit($key, $decayMinutes);
        //$this->limiter->hit($key, $decayMinutes * 60);

        $response = $next($request);

        return $this->addHeaders(
            $response, $maxAttempts,
            $this->calculateRemainingAttempts($key, $maxAttempts)
        );
    }

    protected function buildException($key, $maxAttempts)
    {
        $retryAfter = $this->limiter->availableIn($key);

       //要返回的数据
        $message = json_encode([
            'code' => 429,
            'data' => null,
            'msg' => '您的请求太频繁,已被限制请求',
            'retryAfter' => $retryAfter,
        ], 320);

        $response = new Response($message, 200);

        return $this->addHeaders(
            $response, $maxAttempts,
            $this->calculateRemainingAttempts($key, $maxAttempts, $retryAfter),
            $retryAfter
        );

    }

    protected function addHeaders(\Symfony\Component\HttpFoundation\Response $response, $maxAttempts, $remainingAttempts, $retryAfter = null)
    {
     // 添加 `response` 头 为 `json`
        $response->headers->add(
            ['Content-Type' => 'application/json;charset=utf-8']
        );
        return parent::addHeaders($response, $maxAttempts, $remainingAttempts, $retryAfter);
    }
}
Responses