官方限流组件的两种异常正确处理方式

开发 前端
我们想要的HTTP状态码是429​,响应信息是每个手机号一天最多5条短信​。而这里是500,对应的错误信息是Internal Server Error。

概述

官方限流组件webman限流器,支持注解限流。支持apcu、redis、memory驱动。

文档:https://www.workerman.net/doc/webman/components/rate-limiter.html

接口限流器

参考如下代码

class IndexController
{
    /**
     * @param Request $request
     * @return Response
     */
    public function sendSms(Request $request): Response
    {
        $mobile = $request->get('mobile', '1388888888');
        Limiter::check($mobile, 5, 24*60*60, '每个手机号一天最多5条短信');
        return response_json('短信发送成功');
    }
}

成功响应

HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8

{
    "code": 0,
    "message": "短信发送成功",
    "data": []
}

异常响应

HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8

每个手机号一天最多5条短信

可以看出,限流器会抛出异常,返回的响应信息就是异常的message。并不是我们想要的统一的响应格式。

这里我们使用异常插件:https://www.workerman.net/plugin/16 接管框架的默认异常处理,保证响应格式统一。

修改配置文件config/exception.php

return [
    // 这里配置异常处理类
    '' => \Tinywan\ExceptionHandler\Handler::class,
];

再次请求接口,可以看到异常信息已经被统一处理了。

HTTP/1.1 500 Error
Content-Type: application/json;charset=UTF-8

{
 "code": 0,
 "msg": "Internal Server Error",
 "data": {}
}

但是还不是我们想要的限流异常信息,我们想要的HTTP状态码是429,响应信息是每个手机号一天最多5条短信。而这里是500,对应的错误信息是Internal Server Error。

接着继续改造代码。通过try-catch捕获异常,然后返回自定义的响应信息。

use Tinywan\ExceptionHandler\Exception\TooManyRequestsHttpException;

class IndexController
{
    /**
     * @param Request $request
     * @return Response
     * @throws TooManyRequestsHttpException
     */
    public function sendSms(Request $request): Response
    {
        $mobile = $request->get('mobile', '1388888888');
        try {
            Limiter::check($mobile, 5, 24*60*60, '每个手机号一天最多5条短信');
        } catch (\Throwable $throwable) {
            throw new TooManyRequestsHttpException($throwable->getMessage());
        }
        return response_json('短信发送成功');
    }
}

再次请求接口,可以看到是我们想要的结果信息了。HTTP状态码是429,响应信息是每个手机号一天最多5条短信。

HTTP/1.1 429 Too Many Requests
Content-Type: application/json;charset=UTF-8

{
 "code": 0,
 "msg": "每个手机号一天最多5条短信",
 "data": {}
}

注解限流器

注解限流器使用起来更加简单,只需要在控制器方法上添加注解即可。

use Webman\RateLimiter\Annotation\RateLimiter;

class IndexController
{
    /**
     * @param Request $request
     * @return Response
     */
    #[RateLimiter(3, 60, [IndexController::class, 'getMobile'], '每个手机号一天最多5条短信!')]
    public function sendSms(Request $request): Response
    {
        return response_json('短信发送成功');
    }

    /**
     * @desc 自定义key,获取手机号,必须是静态方法
     * @return string
     */
    public static function getMobile(): string
    {
        return request()->get('mobile','1388888888');
    }
}

请求接口,可以看到异常信息已经被统一处理了。

但不是我们想要的限流异常信息,我们想要的HTTP状态码是429,响应信息是每个手机号一天最多5条短信。而这里是500,对应的错误信息是Internal Server Error。

HTTP/1.1 500 Error
Content-Type: application/json;charset=UTF-8

{
 "code": 0,
 "msg": "Internal Server Error",
 "data": {}
}

继续改造代码。通过自定义异常类限流器的异常,然后返回自定义的响应信息。

这里修改注解的第五个参数,指定异常类为自定义的异常类 Tinywan\ExceptionHandler\Exception\TooManyRequestsHttpException:class

/**
 * @param Request $request
 * @return Response
 */
#[RateLimiter(3, 60, [IndexController::class, 'getMobile'], '每个手机号一天最多5条短信!', TooManyRequestsHttpException::class)]
public function sendSms(Request $request): Response
{
   return response_json('短信发送成功');
}

再次请求接口,可以看到是我们想要的结果信息了。HTTP状态码是429,响应信息是每个手机号一天最多5条短信。

HTTP/1.1 429 Too Many Requests
Content-Type: application/json;charset=UTF-8

{
 "code": 0,
 "msg": "每个手机号一天最多5条短信",
 "data": {}
}
责任编辑:武晓燕 来源: 开源技术小栈
相关推荐

2009-08-17 17:28:23

C#转义字符

2009-08-19 17:30:38

C#转义字符

2017-10-10 15:30:20

JavaScript

2011-07-08 10:57:24

主域控制器额外域控制器AD

2023-07-10 08:00:13

架构Rest返回值

2021-03-31 09:11:27

URLErrorHTTPError

2010-11-12 11:48:15

2010-08-31 09:31:58

Silverlight

2010-11-24 08:54:33

2011-04-06 12:41:41

Java异常

2011-03-03 10:26:04

Pureftpd

2021-05-27 10:57:01

TCP定时器网络协议

2010-08-06 09:38:11

Flex读取XML

2023-03-29 13:06:36

2009-06-25 13:43:00

Buffalo AJA

2010-10-21 16:24:18

sql server升

2010-09-07 11:09:59

2023-11-09 08:14:07

时间窗口限流

2009-12-02 09:49:43

PHP Ajax乱码

2021-09-23 22:36:30

手机数据二手
点赞
收藏

51CTO技术栈公众号