前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Laravel :API 请求频率限制(Throttle中间件),自定义返回JSON类型,自定义时间单位

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

作者头像
Alone88
发布2019-10-22 17:00:31
5.7K0
发布2019-10-22 17:00:31
举报
文章被收录于专栏:Alone88

Laravel api Throttle 请求限制

Laravel (Throttle中间件)

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

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

QQ截图20191007154542.png
QQ截图20191007154542.png

限流原理

  • 获取唯一请求来源,进行唯一标识(key)
  • 获取该请求请求次数 (hits)
  • 判断是否超过最大限制
  • 若达到上限,进入5。未达到,则进入6
  • 丢出访问次数限制异常,结束请求。
  • 首先判断hits 是否达到限制,若未达到,进入7。若达到,进入8。
  • hits 进行计数 + 1,更新到缓存中。 若是第一次,则需要 hits = 1(次数), 并添加访问标识 key (1分钟)到缓存中,以标记请求周期。
  • 请求次数已达到上限(hits >= 60),此时需要判断是否在周期范围内(1分钟),若在周期内,进入9;不在周期内,进入10.
  • 此时请求处在 “1分钟内请求次数达到60次”,即达到限制,返回 false 。
  • 此时请求处在 “不在1分钟内请求次数达到60次”,即不在周期内,需要重新计算周期。

更多参考文档: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),就成限制秒了

代码语言:javascript
复制
<?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);
    }
}

本文由 Alone88 创作,采用 知识共享署名4.0 国际许可协议进行许可 本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名 最后编辑时间为: Oct 7, 2019 at 06:47 pm

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Laravel (Throttle中间件)
    • 限流原理
      • 自定义返回的类型
      相关产品与服务
      消息队列 TDMQ
      消息队列 TDMQ (Tencent Distributed Message Queue)是腾讯基于 Apache Pulsar 自研的一个云原生消息中间件系列,其中包含兼容Pulsar、RabbitMQ、RocketMQ 等协议的消息队列子产品,得益于其底层计算与存储分离的架构,TDMQ 具备良好的弹性伸缩以及故障恢复能力。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档