429 ошибка laravel

Hi, I have been trying for the better part of a week to diagnose why my Laravel 5.7 based API has suddenly started having issues with throttling (429: Too Many Requests). I have (for years) logged every request via a custom middleware and I don’t see nearly enough requests to constitute any throttling. To confirm this I have run Wireshark on both the affected client and the web server during the affected periods. This confirmed that maybe 20 requests happened before my service started responding with the 429: Too Many Requests. I’m lost as to how to proceed with troubleshooting.

Environment:
IIS 10, PHP 7.1.26, Laravel 5.7.25.

Kernel.php

        'api' => [
            'throttle:120,1',
            'bindings',
             AppLibraryCobaltHttpMiddlewareLogMiddleware::class,
        ],

Thanks in advance.

You must be logged in to vote

Have you added logging to the ThrottleRequests middleware?

You must be logged in to vote


1 reply

@dragon99k

Hi, there.
I have similar with this problem and I fixed it.
In RouteServiceProvider.php,
protected function configureRateLimiting()
{
RateLimiter::for(‘api’, function (Request $request) {
return Limit::perMinute(60)->by(optional($request->user())->id ?: $request->ip());
});

    RateLimiter::for('seventy', function () {
        return Limit::perMinute(70);          //You can change this number to avoid 429 error.
    });
}

this code is for Laravel8.0.
If this code help you, I appreciated it.

No, but that is a great idea for a next step. I will update when I know more.

You must be logged in to vote


0 replies

@marlboro if you posted your question elsewhere, could you link it? I’m having similar issues.

You must be logged in to vote


0 replies

@Helveg No, but it’s a bug or configuration issue with either PHP or Laravel. Originally this particular API was only called by one device and there were no issues. We added a second device and suddenly the 429’s started. I would have expected each device (unique IP’s) to get N requests before they got throttled. That is not the case or I would not be having issues.

I ended up just increasing the throttle value large enough to make it stop issuing 429’s. It’s hacky, and I hate it, but I had no other choice. Post a link if you get help somewhere else.

You must be logged in to vote


0 replies

I got the same issue, my throttle was set to 270, and it is still happening, I believe it should be an issue with laravel, because there is no way for me to have 270 calls to my api from one device of testing in 1 minute

You must be logged in to vote


0 replies

I’m currently converting my web app UI to an SPA and running into the same issue. I get the error sporadically when I’m sure I’m nowhere near the limit.

You must be logged in to vote


1 reply

@kristijorgji

This can happen if you have frontend bugs, happened to me as well during infinite reload and SPA was making AJAX calls all the time. Check and fix your JS as well

Just posting this if anyone else was getting the same error.

I was using Memcached as my cache store and after debugging through telnet, I found that it was never expiring my keys. I had to manually restart the service to fix the problem.

Homestead with memcached version 1.5.6.

You must be logged in to vote


1 reply

@cmple

@EvilLooney Your comment seems the most reasonable!
I’m also having this issue with Laravel 8 and PHP8.1 with Memcached on alpine docker.
Were you able to resolve this issue on your without having to restart the caching service?
Thanks!

Did anyone find out the problem? We’re facing same issues here.

You must be logged in to vote


0 replies

Same issue. Laravel 5.7, IIS10, PHP 7.3.

You must be logged in to vote


0 replies

It’s a sporadic recurring issue, all or most of us reporting the issue face it in controlled testing environments as well where we’re sure to be nowhere near the limit. @driesvints can we get some feedback, troubleshooting tips or a timeline on this?

Is there maybe a way that we can log every time a supposed request gets us closer to the throttle limit to debug it?

You must be logged in to vote


0 replies

Also a firefighting tip: you can clear the throttle if it hits your production environment with:

You must be logged in to vote


13 replies

@Helveg Yes, logging can be done on the client. Look in the headers of the response. It should look something like this:

DK@DK:~$ curl -I -X POST http://localhost/fake/path
HTTP/1.1 400 Bad Request
Date: Tue, 01 Oct 2019 20:29:45 GMT
Server: Apache/2.4.39 (Fedora) OpenSSL/1.1.1b
X-Powered-By: PHP/7.2.19
Cache-Control: no-cache, private
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 59
Connection: close
Transfer-Encoding: chunked
Content-Type: application/json

You’re looking for X-RateLimit-Limit and X-RateLimit-Remaining

The issue I was having was in the Kernel. Inside of $middlewareGroups under api, ‘throttle:120,1’ was not being respected. As seen in the headers above, it was always set to 60. Here’s what I needed to do to fix it:

/* ... */

protected $middlewareGroups = [
    'web' => [
        /* .. */
    ],

    'throttle' => ['throttle:99,1'], //No idea why, but this works!

    'api' => [
        'throttle:5000,1', //These values did not change the throttle limit.
        'bindings',
    ],
];

/* ... */

I found this by adding some dump()’s here: https://github.com/laravel/framework/blob/5.7/src/Illuminate/Routing/MiddlewareNameResolver.php#L29

You must be logged in to vote


5 replies

@charlieuki

I think the throttle under api section only affects routes for API.

@pellexa

‘throttle’ => [‘throttle:99,1’], //No idea why, but this works!

This works because the throttle middleware is registered here for the /token route.

@kelvinthiongo

You just saved my multimillion dollars project.

@billanguyen1990

@ajaykumar890

thanks for this wonderful answer

Also a firefighting tip: you can clear the throttle if it hits your production environment with:

worked thanks

You must be logged in to vote


0 replies

I had to remove the throttling from the api middleware in appHttpKernel.php. Just delete the following line in appHttpKernel.php

'throttle:60,1',

You must be logged in to vote


0 replies

That’s not very good advice: the throttle is there for good reasons. You’re now vulnerable to being spammed with requests such as login requests. Never advice to completely disable security measures even if they aren’t functioning properly

You must be logged in to vote


0 replies

That’s not very good advice: the throttle is there for good reasons. You’re now vulnerable to being spammed with requests such as login requests. Never advice to completely disable security measures even if they aren’t functioning properly

I do agree that any good system architecture should incorporate the necessary security measures. However, these measures should be supplemented with a good understanding of the internals. My response was in the context of the specific OP query assuming they know what they are doing, and not a general system architecture advice.

Also, most apps would use the web middleware for website functions such as Login. Laravel 6.x does not enforce any throttling for this middleware out-of-the box so it would be vulnerable to spamming, unless the developer knows what they are building and incorporates the necessary guards.

Your thoughts are absolutely valid and I appreciate you providing the helpful perspective here. I just wanted to make sure that people who find the solution helpful would know what they are working with.

Cheers!

You must be logged in to vote


0 replies

how to increase request limit in laravel.

You must be logged in to vote


1 reply

@AsifMian

in appHttpKernel.php

‘api’ => [

        'throttle:2,1', //means 2 requests per minute we can increase it to as we want like 200000
       
    ],

FWIW — I was causing this issue with the «infinite loop» situation with useEffect() in React. I added the empty array to stop triggering repeated requests.

You must be logged in to vote


2 replies

@Rizzeol

Hi @sloan58 Can you explain what exactly you did? php artisan cache:clear didn’t worked for me. I think it is because of useEffect() in my react app.

Thanks in advance. :)

@sloan58

Hi @Rizzeol,

Sure thing! There’s a second parameter you can pass to useEffect to specify the data you want to watch so that useEffect fires when that data changes. If you pass an empty array (don’t watch anything), it won’t keep re-rendering when the component updates.

useEffect(() => {
    doSomethingOnce();
}, []);

i do not recommend removing throttling, it’s a huge security risk,like DOD and DDOS attacks

You must be logged in to vote


2 replies

@fightborn

You can, and should rate limit using the webserver, not using PHP itself. It’s one of the worst decisions ever. You won’t avoid DDOS using Laravel’s rate limiting, it still needs to accept the request, check if it’s over the limit and then send the output. You effectively did nothing to prevent DDOS.

The only sane decision is to approach the rate limiting without involving PHP as you want the request to be denied before it even makes PHP do any processing at all.

Throttling via nginx is trivial, easy to understand and best part: actually works.

@paras-malhotra

Nginx throttling is good for sure, but that doesn’t mean Laravel throttling is bad. There are different use cases for both. For instance, you may be able to throttle by IP address with Nginx, but throttling by username or a combination of username/IP or say user ID would be a better case for Laravel.

Also, DDOS attacks are distributed. Even Nginx can’t save you from DDOS. There are other strategies for those kinds of attacks.

Hello,

I tried to comment
//'throttle' => IlluminateRoutingMiddlewareThrottleRequests::class,
and
'api' => [ //'throttle:60:1', IlluminateRoutingMiddlewareSubstituteBindings::class, ],

It worked for me. Sorry for the typo

You must be logged in to vote


0 replies

Hi everyone, so, is there a proper way to fix this issue without disabling throttle if I’m using Sanctum for my API authentication and Fortify for my web authentication?

You must be logged in to vote


0 replies

My guess is that you’re using a login proxy to passport so server is requesting tokens rather than the user. You should disable the throttling specifically for localhost (ips from server).

You must be logged in to vote


0 replies

Am using Laravel 8 for my API and I have a couple of clients accessing my API. Recently I started to get 429 HTTP response after I added some new clients.

What I found out is that, by default rate limit is not IP specific, so when I added more clients (each client has its own IP) I started to get 429. I modified rate limit to use IP and this solved the issue for me.

This is how I did that.

File path app/Providers/RouteServiceProvider.php
Before (IP agnostic rate limiting)

RateLimiter::for('api-rate-limit', function (Request $request) {
    return Limit::perMinute(120);
});

After (IP aware rate limiting)

RateLimiter::for('api-rate-limit', function (Request $request) {
    return Limit::perMinute(120)->by($request->ip());
});

More information on how to do this with Laravel 8 can be found here. And also there is a nice explanation about it in Laracasts. It is also possible to set up rate limiting per route, (for example api/images) instead of a route group like api/.

Also to keep in mind is that this is Laravel 8 way of rate limiting. For versions below 8, rate limiting is done differently. But I assume it is possible to rate limit per IP and per route in versions below 8.

Also I think, in general, it is worthwhile to try out IP specific and/or route specific rate limit instead of removing rate limit completely or increasing rate limit to a very high value.

You must be logged in to vote


1 reply

@nagra

Since you can get people on the same IP, you can also change it to use the Bearer token of the user.
This is how twitter API does it.

In laravel version above 7.x php artisan optimize:clear will help you

You must be logged in to vote


1 reply

@salanta-net

if someone is using Fortify there is a ‘limiters’ of five request per minute. Just comment the ‘login’ it!

/*
|--------------------------------------------------------------------------
| Rate Limiting
|--------------------------------------------------------------------------
|
| By default, Fortify will throttle logins to five requests per minute for
| every email and IP address combination. However, if you would like to
| specify a custom rate limiter to call then you may specify it here.
|
*/

'limiters' => [

// ‘login’ => ‘login’,
‘two-factor’ => ‘two-factor’,
],

 protected $middlewareGroups = [
        'web' => [
            AppHttpMiddlewareEncryptCookies::class,
            IlluminateCookieMiddlewareAddQueuedCookiesToResponse::class,
            IlluminateSessionMiddlewareStartSession::class,
            // IlluminateSessionMiddlewareAuthenticateSession::class,
            IlluminateViewMiddlewareShareErrorsFromSession::class,
            AppHttpMiddlewareVerifyCsrfToken::class,
            IlluminateRoutingMiddlewareSubstituteBindings::class,
        ],

        'api' => [
            // LaravelSanctumHttpMiddlewareEnsureFrontendRequestsAreStateful::class,
            'throttle:200,1',
            IlluminateRoutingMiddlewareSubstituteBindings::class,
        ],
    ];
You must be logged in to vote


0 replies

I experiences this because it was IP address driven and perhaps the users internet provider reused the IP addresses of their customers making anonymous users appears to be the same person, hitting too many times.

Has anyone else experienced this?

I want to suggest it might be cloudflare related but I think the code accounts for the use of cloudflare’s request headers.

You must be logged in to vote


0 replies

@marlboro were you able to resolve this issue? If so, how?
Thanks man!

You must be logged in to vote


0 replies

Definig Rate Lminters

`use IlluminateCacheRateLimitingLimit;
use IlluminateHttpRequest;
use IlluminateSupportFacadesRateLimiter;

/**

  • Configure the rate limiters for the application.
  • @return void
    */
    protected function configureRateLimiting()
    {
    RateLimiter::for(‘global’, function (Request $request) {
    return Limit::perMinute(1000);
    });
    }`
You must be logged in to vote


0 replies

@marlboro I have experienced this kind of issue and made me panic. My solution is to change the CACHE_DRIVER to array in your .env file.
CACHE_DRIVER=array

You must be logged in to vote


0 replies

Данная ошибка говорит нам о том что мы превысили лимит запросов.
По умолчанию Laravel дает нам 60 запросов в минуту в нашему апи.

Для исправления количества запросов идем в файл

app/Http/Kernel.php

находим строчку

'throttle:6000,1',

и исправляем на нужное нам количество запросов.

Так-же можно прописать необходимый лимит на конкретный роут

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

*1. The user sent too many requests within the specified time. Used to limit the rate. It can be used as an access restriction module

//Define intermediate routes
Route::middleware('throttle:login')->group(function (){
    Route::get('login',[LoginController::class,'login']);
    Route::get('logindo',[LoginController::class,'loginDo']);
});

The parameter in the minute is the corresponding access frequency limit

2. Register the middleware and define the middleware in the kernel to be used for middleware interception

Route::group(['prefix'=>'wechat','namespace'=>'Api','middleware'=>'checklogin'],function (){
    Route::get('login',[LoginController::class,'login']);
    Route::get('logindo',[LoginController::class,'loginDo']);
});
<?php
class Mysql{
    private static $mysql=null;
 
    private function __clone()
    {
        // TODO: Implement __clone() method.
    }
 
    private function __construct()
    {
 
    }
    //entrance
    public static function concent(){
        if (self::$mysql===null){
            try {
                self::$mysql=mysqli_connect('Host number','account','password','Library name');
            }catch(Exception $e){
                return ['connection failed'.$e->getMessage()];
            }
        }
        if (!self::$mysql instanceof self){
            try {
                self::$mysql=mysqli_connect('Host number','account','password','Library name');
            }catch(Exception $e){
                return ['connection failed'.$e->getMessage()];
            }
        }
        return  self::$mysql;
    }
}
    var_dump($obj=Mysql::concent('Host number','account','password','Library name'));

I tried everything including the Best Answer but it just didn’t work.

Therefore, not even changing the RateLimiter in the FortifyServiceProvider class.

I’d try to log in and get a 429 error after just one login attempt.

Here what was the issue for me, it was the the config/fortify.php file.

I had to change:

    /*
    |--------------------------------------------------------------------------
    | Rate Limiting
    |--------------------------------------------------------------------------
    |
    | By default, Fortify will throttle logins to five requests per minute for
    | every email and IP address combination. However, if you would like to
    | specify a custom rate limiter to call then you may specify it here.
    |
    */

    'limiters' => [
        'login' => 'login',
        'two-factor' => 'two-factor',
    ],

to

    /*
    |--------------------------------------------------------------------------
    | Rate Limiting
    |--------------------------------------------------------------------------
    |
    | By default, Fortify will throttle logins to five requests per minute for
    | every email and IP address combination. However, if you would like to
    | specify a custom rate limiter to call then you may specify it here.
    |
    */

    'limiters' => [
        'login' => 5,
        'two-factor' => 5,
    ],

And funny enough the problem is inherent in the Fortify package itself when you run:

php artisan vendor:publish --provider="LaravelFortifyFortifyServiceProvider" as per their documentation instructions.

This fundamental reason being that code within vendor/laravel/framework/src/Illuminate/Routing/Middleware/ThrottleRequests.php is not able to correctly parse the limit:

    /**
     * Resolve the number of attempts if the user is authenticated or not.
     *
     * @param  IlluminateHttpRequest  $request
     * @param  int|string  $maxAttempts
     * @return int
     */
    protected function resolveMaxAttempts($request, $maxAttempts)
    {
        if (Str::contains($maxAttempts, '|')) {
            $maxAttempts = explode('|', $maxAttempts, 2)[$request->user() ? 1 : 0];
        }

        if (! is_numeric($maxAttempts) && $request->user()) {
            $maxAttempts = $request->user()->{$maxAttempts};
        }

        return (int) $maxAttempts;
    }

, which means, 'login' is just parsed as 0 and that’s what it returns.

Now I don’t have to run php artisan cache:clear just to test.

Skip to content

I’m using a load test tool called Artillery to simulate requests on my Laravel application. By default the Laravel application uses the IP to detect whether it should rate limit or not, so in production the varying IP addresses won’t be a problem, but for Artillery this is a problem since the requests are returning 429 errors.

I’ve tried disabling configureRateLimiting in production, but I’m still getting 429 errors.

Artillery is sending at least 3 requests per second to my api endpoint for at least 2 minutes, and then ramps up to roughly 30 a second for 15 minutes.

What am I missing to disable rate limiting here?

<?php

namespace AppProviders;

use IlluminateCacheRateLimitingLimit;
use IlluminateFoundationSupportProvidersRouteServiceProvider as ServiceProvider;
use IlluminateHttpRequest;
use IlluminateSupportFacadesRateLimiter;
use IlluminateSupportFacadesRoute;

class RouteServiceProvider extends ServiceProvider
{
    /**
     * The path to the "home" route for your application.
     *
     * This is used by Laravel authentication to redirect users after login.
     *
     * @var string
     */
    public const HOME = '/home';

    /**
     * The controller namespace for the application.
     *
     * When present, controller route declarations will automatically be prefixed with this namespace.
     *
     * @var string|null
     */
    // protected $namespace = 'App\Http\Controllers';

    /**
     * Define your route model bindings, pattern filters, etc.
     *
     * @return void
     */
    public function boot()
    {
        if (!config('artillery.enabled')) {
            $this->configureRateLimiting();
        }

        $this->routes(function () {
            Route::prefix('api')
                ->middleware('api')
                ->namespace($this->namespace)
                ->group(base_path('routes/api.php'));

            Route::middleware('web')
                ->namespace($this->namespace)
                ->group(base_path('routes/web.php'));
        });
    }

    /**
     * Configure the rate limiters for the application.
     *
     * @return void
     */
    protected function configureRateLimiting()
    {
        if (config('artillery.enabled')) {
            return;
        }

        RateLimiter::for('api', function (Request $request) {
            return Limit::perMinute(300)->by(optional($request->user())->id ?: $request->ip());
        });
    }
}

My site goes through Cliudflare and I’m sending requests to my production endpoint since this is the most realistic test.

>Solution :

In app/Http/Kernel.php Laravel has a default throttle limit for all api routes.

protected $middlewareGroups = [
    ...
    'api' => [
        'throttle:60,1',   //comment means it would be no limit
    ],
];

Comment or increase it.

Понравилась статья? Поделить с друзьями:

Не пропустите эти материалы по теме:

  • Яндекс еда ошибка привязки карты
  • 428b ошибка бмв e70 m57n2
  • 428b ошибка bmw
  • 42883 ошибка postgresql
  • 428 ошибка меркурий

  • 0 0 голоса
    Рейтинг статьи
    Подписаться
    Уведомить о
    guest

    0 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии