Heim > Fragen und Antworten > Hauptteil
Gibt es eine Möglichkeit, eine Ratenbegrenzung auf eine Route anzuwenden, jedoch nur bei erfolgreichen Antworten. Wenn der Benutzer beispielsweise fünfmal eine Anfrage an den send/code
-Endpunkt sendet und alle erfolgreich sind, wird der Benutzer daran gehindert, die Anfrage erneut zu senden. Wenn jedoch zwei davon fehlschlagen (z. B. ein Validierungsfehler oder ein anderes Problem), drei jedoch erfolgreich sind, sollte der Benutzer es innerhalb der vorgegebenen Zeit noch zweimal versuchen.
Ich weiß, dass man vor der Ausführung der Anfrage eine Überprüfung des Ratenlimits durchführen und den Benutzer dann blockieren oder weitermachen lassen kann. Aber gibt es eine Möglichkeit, meine Logik anzuwenden, oder sollte ich einen anderen Ansatz ausprobieren?
P粉9869374572024-01-06 17:02:10
这是源代码
use Illuminate\Support\Facades\RateLimiter; class CodeZiDotProTestRateLimit extends Controller{ public function test_rate_limit_only_success(Request $request){ // Step 1: Validate the request data $validator = Validator::make($request->all(), [ 'name' => 'required|string', 'email' => 'required|email', 'password' => 'required|min:8', ]); if ($validator->fails()) { return response()->json(['errors' => $validator->errors()], 422); } // Step 2: Apply rate limiting to this controller action $key = 'test_rate_limit_only_success_by_ip_'.request()->ip(); if (RateLimiter::tooManyAttempts($key,10)) { return response()->json(['errors' => 'You have made too much in a short time. Please wait after 1 minute'], 422); } else { RateLimiter::hit($key, 60); } }
}
假设我的网址是 Example.com/test_Rate_Limit_only_success。
在此示例中,当用户向系统发送请求时,应用程序仍会验证该请求(如果出现错误,用户将发送无限制的请求)。在数据有效的情况下,限速部分将开始工作。
P粉5125267202024-01-06 09:10:49
您可能需要制作自己的中间件,但您可以扩展 ThrottleRequests
类并自定义您想要处理响应的方式:
<?php namespace App\Http\Middleware; use Closure; use Illuminate\Routing\Middleware\ThrottleRequests; use Illuminate\Support\Arr; class ThrottleSuccess extends ThrottleRequests { /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @param array $limits * @return \Symfony\Component\HttpFoundation\Response * * @throws \Illuminate\Http\Exceptions\ThrottleRequestsException */ protected function handleRequest($request, Closure $next, array $limits) { $response = $next($request); // call the controller first if ($response->statusCode === 200) { // only hit limiter on successful response foreach ($limits as $limit) { if ($this->limiter->tooManyAttempts($limit->key, $limit->maxAttempts)) { throw $this->buildException($request, $limit->key, $limit->maxAttempts, $limit->responseCallback); } $this->limiter->hit($limit->key, $limit->decayMinutes * 60); } } foreach ($limits as $limit) { $response = $this->addHeaders( $response, $limit->maxAttempts, $this->calculateRemainingAttempts($limit->key, $limit->maxAttempts) ); } return $response; } }
然后将您的中间件添加到Kernel.php
:
protected $routeMiddleware = [ // ... 'throttle.success' => ThrottleSuccess::class, // ... ];
然后像原来的throttle中间件一样在路由中使用它:
Route::middleware('throttle.success:5,1')->group(function () { // ... });
注意:如果您想返回从 RateLimiter::for
构建的自定义响应,您可能必须重写 handleRequestUsingNamedLimiter
,我在这里没有为此做任何事情。< /p>