Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel override group middleware

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 ?

like image 802
Miljan Rakita Avatar asked May 31 '19 00:05

Miljan Rakita


People also ask

How is middleware applied to a group of routes?

Assigning Middleware To Routes If you would like to assign middleware to specific routes, you should first assign the middleware a key in your application's app/Http/Kernel.php file. By default, the $routeMiddleware property of this class contains entries for the middleware included with Laravel.

How many types of middleware are there in Laravel?

There are two types of Middleware in Laravel. The Global Middleware will run on every HTTP request of the application, whereas the Route Middleware will be assigned to a specific route. The middleware can be registered at app/Http/Kernel.


2 Answers

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'));
    }
    
like image 128
nvahalik Avatar answered Oct 30 '22 16:10

nvahalik


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.

like image 38
Jeffrey Avatar answered Oct 30 '22 15:10

Jeffrey