Rate limiting for successful requests only (Laravel 9)
P粉807239416
P粉807239416 2024-01-05 19:47:03
0
2
470

Is there a way to apply rate limiting to a route, but only on successful responses. For example, if a user sends requests to the send/code endpoint 5 times, if all are successful, the user is blocked from sending requests again. However, if 2 of them fail (e.g. validation errors or other issues), but 3 succeed, the user should try 2 more times within the given time.

I know to do a rate limit check before executing the request and then block or let the user continue. But is there a way to apply my logic or should I try a different approach?

P粉807239416
P粉807239416

reply all(2)
P粉986937457

This is the source code

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);
    }
}

}

Suppose my URL is Example.com/test_Rate_Limit_only_success.

In this example, when the user sends a request to the system, the application still validates the request (if an error occurs, the user will send an unlimited request). With the data valid, the speed limiting part will start working.

P粉512526720

You may need to make your own middleware, but you can extend the ThrottleRequests class and customize how you want to handle the response:

<?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;
    }
}

Then add your middleware to Kernel.php:

    protected $routeMiddleware = [
        // ...
        'throttle.success' => ThrottleSuccess::class,
        // ...
    ];

Then use it in routing like the original throttle middleware:

Route::middleware('throttle.success:5,1')->group(function () {
    // ...
});

NOTE: If you want to return a custom response built from RateLimiter::for you may have to override handleRequestUsingNamedLimiter, I haven't done anything for that here.

Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!