Maison > Questions et réponses > le corps du texte
Existe-t-il un moyen d'appliquer une limite de débit à un itinéraire, mais uniquement sur les réponses réussies. Par exemple, si l'utilisateur envoie une requête au point de terminaison send/code
5 fois, si toutes réussissent, l'utilisateur ne peut pas envoyer à nouveau la requête. Cependant, si 2 d’entre eux échouent (comme une erreur de validation ou un autre problème), mais que 3 réussissent, l’utilisateur doit essayer 2 fois de plus dans le délai imparti.
Je sais qu'il faut vérifier la limite de débit avant d'exécuter la demande, puis bloquer ou laisser l'utilisateur continuer. Mais existe-t-il un moyen d’appliquer ma logique ou dois-je essayer une approche différente ?
P粉9869374572024-01-06 17:02:10
Voici le code source
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); } }
}
Supposons que mon URL soit Exemple.com/test_Rate_Limit_only_success.
Dans cet exemple, lorsque l'utilisateur envoie une requête au système, l'application valide toujours la requête (si une erreur se produit, l'utilisateur enverra une requête illimitée). Avec les données valides, la partie limitation de vitesse commencera à fonctionner.
P粉5125267202024-01-06 09:10:49
Vous devrez peut-être créer votre propre middleware, mais vous pouvez étendre la classe ThrottleRequests
et personnaliser la façon dont vous souhaitez gérer la réponse :
<?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; } }
Puis ajoutez votre middleware à Kernel.php
:
protected $routeMiddleware = [ // ... 'throttle.success' => ThrottleSuccess::class, // ... ];
Ensuite, utilisez-le dans des itinéraires comme le middleware d'accélérateur d'origine :
Route::middleware('throttle.success:5,1')->group(function () { // ... });
Remarque : Si vous souhaitez revenir de RateLimiter::for
构建的自定义响应,您可能必须重写 handleRequestUsingNamedLimiter
, je n'ai rien fait pour cela ici. < /p>