6
votes

How to override group middleware? What i want to achieve is to add other throttle limit for register/login routes.

My current throttle is set in kernel.

'api' => [
        'throttle:40,1',
        'bindings',
    ],

I want to set new throttle limit for login/register routes.

This is how i did it.

Route::post('login', 'Api\UserController@login')->middleware('throttle:15,3')->name('user.login');
Route::post('register', 'Api\UserController@register')->middleware('throttle:15,3')->name('user.register');

When i run php artisan route:list it says that this middleware api,throttle:15,3 is applied to this route.

The problem is when i run login request, response header says

X-RateLimit-Limit       40
X-RateLimit-Remaining   38

So as far as i see my new middleware is not applied. But my throttle requests are counted twice. How can i apply different middleware for throttle on login/register routes and override the old one ?

2

2 Answers

1
votes

Had this same question and just did some research. It doesn't appear that there is a way to overwrite the middleware configuration.

I, too, see that my middleware has updated in route:list but when resolving the middleware, it always uses a merged set of rules and so that initial api rule will end up overriding anything that defines something else over that.

You have a couple of options:

  1. Remove the throttle rule from the Kernel api middleware definition and then use a Route::group() to re-add that specific rule to the rest of the routes. Then, in the same file, you can create a new Route::group() which defines the custom throttle config.

    Route::group(['middleware' => 'throttle:120,1'], function () {
         ...
    });
    
    Route::group(['middleware' => 'throttle:15,3'], function () {
         ...
    });
    
  2. Create a custom api-auth.php file which is wrapped in a custom middleware group that you define just like the default api middleware. (You'll need to add another call in your RouteServiceProvider to load it like this:

    public function map() { 
        ...
        $this->mapCustomAuthRoutes();
    }
    
    protected function mapCustomAuthRoutes()
    {
        Route::middleware(['throttle:15,3', 'bindings'])
            ->namespace($this->namespace)
            ->as('api.')
            ->group(base_path('routes/api-auth.php'));
    }
    
0
votes

Old topic, but its the first i found; time for an updated answer.

I've had this problem in the past as well. My solution back then was to add the middleware in the constructor of the controllers. I dislike it but it works.

I'm currently using Laravel 8 with a new project and found that the following solution works:

  1. Set the default middleware in kernel.php
'api' => [
        'throttle:40,1',
        'bindings',
    ],
  1. Remove the middleware throttle:40,1 from the specific route, and add the correct middleware throttle:15,3:
Route::post('login', 'Api\UserController@login')->withoutMiddleware('throttle:40,1')->middleware('throttle:15,3')->name('user.login');

If you do not remove the middleware, it will run the throttle middleware twice per request.

I also played around with $this->middleware( 'throttle:40,1' )->except( ['login'] ) in the constructor of Api\UserController, however that does not give the required result; it will just add the middleware for all but one method, it does not overwrite.