Laravel 5.4 - 覆盖 API 'throttle:60,1'

28

我正在编写许多API来获取和存储数据。
我喜欢默认的throttle选项:


我喜欢默认的throttle选项:

protected $middlewareGroups = [
    'api' => [
        'throttle:60,1',
        'bindings',
    ],
];

为了将请求限制在每分钟60次,但对于某些路由(例如:POST),我想增加这个值。

我尝试像下面这样在路由中间件上设置'throttle:500,1'

Route::group(function () {
        Route::get('semaphore/1',        ['uses' => 'App\Api\V1\DBs\SemaphoreController@index']);
        Route::post('semaphore/1',       ['uses' => 'App\Api\V1\DBs\SemaphoreController@store',        'middleware' => 'WriteToDatabaseMiddleware', 'throttle:500,1']);
});

但它不起作用。

有什么想法吗?

谢谢。

更新:
我注意到在api.php路由中使用的'throttle:500,1'会在Kernel.php文件中指定的默认'throttle:60,1'之后设置;因此,它无效。

记录过程执行情况,第一个调用是:

Illuminate\Routing\Middleware\ThrottleRequests -> handle

Kernel.php 中可以看出最大尝试次数为 60

接着,第二个调用是:

Illuminate\Routing\Middleware\ThrottleRequests -> handle

api.php的代码中可以看出,最大尝试次数为500

换句话说,api.php文件中的throttle:500,1不会覆盖Kernel.php文件中的throttle:60,1

3个回答

21

当前回答

根据这个GitHub问题,限速中间件不应该"两次"使用(就像您想要那样)。解决您当前的问题只有两种正确的方法:

  1. 编写自己的限速中间件

或者

  1. 为每个路由(组)单独定义限速中间件

旧回答

您设置了错误的中间件键!在声明要使用的多个中间件时,请为它们创建一个新数组。

['middleware' => ['WriteToDatabaseMiddleware','throttle:500,1']]

编辑:由于中间件顺序的原因,您应该将内核限制设置为您想要使用的最高值,并将所有其他需要有较低限制值的路由设置为相应的值。


我在我的代码上进行测试,但它不起作用;我已经更新了我的问题并进行了调查。 - vlauciani
@vlauciani 那么你应该将内核值更改为 throttle:500,1(更高的值),并将所有其他需要进行节流控制的路由设置为 throttle:60,1。这样可以按照请求顺序进行处理。 - manniL
是的,你的解决方案是我的想法... 问题在于使用这种方法会将所有路由设置为 500;然后我必须记住为每个新路由设置为 60。我更喜欢有一个标准值(例如:60),并仅覆盖特定路由到 500 - vlauciani
@vlauciani 我理解你的观点。无论如何,因为问题似乎出在 Laravel 网站上,最好在他们的 GitHub 存储库上创建一个问题。我在这里做不了更多 :| - manniL
1
谢谢@manniL,我现在看到了你的“当前答案”。好的,它澄清了操作;我想解决方案是创建自己的节流中间件。再次感谢你。 - vlauciani
显示剩余3条评论

3
在Laravel 6中,你可以使用前缀来防止全局限流。使用'throttle:5,1,prefix'
Route::group(['prefix' => 'contact-us', 'middleware' => 'throttle:5,1,contact-form',], function () {
    Route::post('/', 'ContactUsController@store');
});

允许根据名称设置多个节流器


1
Laravel 5.9?你是不是指的是 Laravel 6。在 5.8 之后,Laravel 转向语义化版本控制,从 6.0.0 开始。 - Andrew Bibby
嗨,Andrew,版本5.9有误,请修正我的回答。 如果您想在节流中间件中使用前缀,这个拉取请求可能会对您有所帮助 允许通过命名使用多个限流器 - Ali Yousefi

2

目前的回答都没有解释 Laravel 5.x 的行为。在该版本中,每个“throttle”的实例都使用相同的桶。因此,如果您在两个不同的位置放置一个限制速率命令,它将影响每个实例。

考虑以下示例:

// User can email 5 times an hour
Route::post('/email', 'Ctrl@email')->middleware('throttle:5,60');
// User can search 100 times an hour
Route::get('/search', 'Ctrl@search')->middleware('throttle:100,60);

如果用户在5分钟内搜索5次,则下一小时将无法发送电子邮件。
在Laravel 5.x中,没有办法解决这个问题。从Laravel 6开始,它们增加了对流量名称的支持, 给它们分配了单独的存储桶。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接