Maison  >  Questions et réponses  >  le corps du texte

Limitation de débit pour les demandes réussies uniquement (Laravel 9)

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粉807239416P粉807239416311 Il y a quelques jours474

répondre à tous(2)je répondrai

  • P粉986937457

    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.

    répondre
    0
  • P粉512526720

    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>

    répondre
    0
  • Annulerrépondre