Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[5.0] Ability to add Kernel middleware at runtime #6211

Closed
rcrowe opened this issue Oct 24, 2014 · 30 comments
Closed

[5.0] Ability to add Kernel middleware at runtime #6211

rcrowe opened this issue Oct 24, 2014 · 30 comments

Comments

@rcrowe
Copy link

rcrowe commented Oct 24, 2014

I need to add middleware to the kernel at runtime from a service provider. Something along the lines of:

public function addMiddleware($middleware)
{
    $this->middlware[] = $middlware;
}
@GrahamCampbell
Copy link
Member

Just call the middleware method on the router class.

@rcrowe
Copy link
Author

rcrowe commented Oct 24, 2014

Thats not the same. That middleware doesn't run on every request, right?

@GrahamCampbell
Copy link
Member

Ahh, yes. I see what you mean now.

@GrahamCampbell
Copy link
Member

It would be really cool to have a way to do this because the current way to do it relies on modifying the Kernel class.

@rcrowe
Copy link
Author

rcrowe commented Oct 24, 2014

By the time the service provider is called, seems to late to add anything into the kernel.

Right now, you have to add both a service provider & the middleware config. Would be nice to just add the 1 & have it work.

@GrahamCampbell
Copy link
Member

Yeh, I agree.

@memtoko
Copy link

memtoko commented Oct 27, 2014

I don't know this work or not, I think it's possible though. Maybe something like this:

$this->app['events']->listen('router.matched', function($route, $request)
{
    $middleware = array_pluck($route->middleware(), 'yourmiddleware');

    $routeAction =  $route->getAction();
    //replace with your middleware
    $routeAction['middleware'] = $middleware;

       //replace route actions
    $route->setAction($routeAction);
});

@barryvdh
Copy link
Contributor

I would also like this. This is actually possible in L4, so I'm assuming this request is for L5?

In my case, I use a Middleware for https://github.com/barryvdh/laravel-debugbar and https://github.com/barryvdh/laravel-cors because Middleware is run also on errors, and the after-filter isn't. But haven't looked into L5.0 much, so not sure if this isn't possible yet.

@rcrowe rcrowe changed the title Ability to add Kernel middleware at runtime [5.0] Ability to add Kernel middleware at runtime Nov 2, 2014
@rcrowe
Copy link
Author

rcrowe commented Nov 2, 2014

Anyone found a way around this yet from a service provider, until hopefully it's added back in?

@coolhome
Copy link
Contributor

This would be useful for packages that need to add middleware. +1 from me.

@tiran133
Copy link

I added a method addMiddleware() to my App\Http\Kernel class.
Now I can add middlewares in my ServiceProviders. At least in my own Projects.
For package development this method should be part of the core.

$this->app['Illuminate\Contracts\Http\Kernel']->addMiddleware('Middleware');

The bootstrap happens before the request get send through the middleware stack.

See. Illuminate\Foundation\Http\Kernel.php

protected function sendRequestThroughRouter($request)
    {
        $this->app->instance('request', $request);

        $this->bootstrap();

        return (new Pipeline($this->app))
                    ->send($request)
                    ->through($this->middleware)
                    ->then($this->dispatchToRouter());
    }

@Beanow
Copy link

Beanow commented Feb 6, 2015

+1 for this feature from me.

@Beanow
Copy link

Beanow commented Feb 6, 2015

@barryvdh, from above duplicate issue:

Yes, would like that too.
I think the argument against that was that it would be difficult to manage the order of the middleware.

There is already limited control of the ordering of things. First global middleware, then before filters, then route middleware, etc.

If your ordering matters, you can always consider not to add the global middleware through your MyServiceProvider@boot method, but ask implementers to add them to the kernel manually.

@asoseil
Copy link

asoseil commented Feb 11, 2015

so is there no solution?

@GrahamCampbell
Copy link
Member

None that I'm aware of.

@Beanow
Copy link

Beanow commented Feb 12, 2015

So far I've only come up with a workaround that only partially solves the issue of ordering.
By all means I do not recommend this for everyone it's highly dependant on your situation.

What currently solves my problems is that I'm using an event handler on router.matches (called after the global middleware and before the route middleware). This event handler does a last minute modification of the route middleware to add mine. You can think of your own algorithm of how to add it, but I went with: add it as first middleware unless it's already defined. Meaning a programmer can override the location, but the default is auto-addition to the front.

@jasonlewis
Copy link
Contributor

I'm going to submit a pull for this. I agree with the above statement in that if ordering really matters then it can be added manually.

Best to probably check in the addMiddleware method if the middleware already exists and if so skip it. That way the end-user of the package can adjust the order if required.

@barryvdh
Copy link
Contributor

FYI, this has been added (see above PR)
https://github.com/laravel/framework/blob/v5.0.14/src/Illuminate/Foundation/Http/Kernel.php#L154-L184

This issue can be closed.

@GrahamCampbell
Copy link
Member

Thanks @barryvdh.

@GrahamCampbell
Copy link
Member

And @jasonlewis. :)

@martinschaepker
Copy link

is there a way to add $routeMiddelware at runtime?

@jaumesala
Copy link

I'm trying to figure out where's the best place to add a call to prependMiddleware for a service provider that is only necessary for a development environment.

To be precise, I have a project with the clockwork package installed for debugging reasons.
I've extracted the binding of the package's serviceProvider and I've placed it in the App\Providers\AppServiceProvider.php.

But to be honest, I'm struggling to find the correct place to add the next piece of code (or whatever is needed to accomplish this action...):

if (config('app.debug'))
{
    $kernel->prependMiddleware('Clockwork\Support\Laravel\ClockworkServiceProvider');
}

Basically I don't know when/where is the best moment, during the request lifecycle...
@GrahamCampbell @barryvdh @AnyBody any suggestion?

Btw, I've tried this example but I get an error...

@GrahamCampbell
Copy link
Member

Please ask on the forums.

@0xMatt
Copy link
Contributor

0xMatt commented May 7, 2015

Any plans on getting this fixed for package maintainers in 5.1?

@Sladewill
Copy link

It has been added we are already using the fix our packages, recheck barrys commit which adds the methods.

@0xMatt
Copy link
Contributor

0xMatt commented May 8, 2015

You're right, I was using App\Http\Kernel which doesn't work, my apologies.

@mreschke
Copy link

It is great that we now have the ability to add dynamic global middleware with

// Register Middleware
$kernel = $this->app->make('Illuminate\Contracts\Http\Kernel');
$kernel->pushMiddleware('Mrcore\Modules\Wiki\Http\Middleware\AnalyzeRoute');

BUT we still need the ability to define route based middleware as well. This is critical with adding packages that require their own custom middleware. Without this feature, the packages has to resort back to using Laravel 4 Filters.

Started a new issues about this at #8917

@cydrickn
Copy link

cydrickn commented Jul 6, 2015

Maybe this one can help you guys.
This code is for route middleware
Add this code to any service provider

$this->app['router']->middleware('yourroutermiddleware','Your\Class\Middleware');

change the yourroutermiddleware, etc. backendauth
change the Your\Class\Middleware to your Middleware class, etc. Example\Vendor\MyMiddleware

sample router

Route::get("yoururl",["middleware" => "backendauth",function(){}]);

This code is tested and working.

@mreschke
Copy link

mreschke commented Jul 7, 2015

Yes that is what crynobone's replied in #8917 and it works. So we can dynamically add both global middleware with prependMiddleware() and pushMiddleware() and route based middleware with

public function boot(\Illuminate\Routing\Router $router) {
    $router->middleware('name', 'MiddlewareClass');
}

@mohamedsharaf
Copy link
Contributor

@GrahamCampbell
in 5.2 there is Middleware groups
need to push and prependMiddleware to a group say "web"
#12141

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests