braxton's avatar

"Web" middleware in Laravel 5.2

Hello, since Laravel 5.2 just released today, I want to experement around and see if I'd like to update my applications to 5.2, when I was looking at the routes.php file, I came across this:

/*
|--------------------------------------------------------------------------
| Application Routes
|--------------------------------------------------------------------------
|
| This route group applies the "web" middleware group to every route
| it contains. The "web" middleware group is defined in your HTTP
| kernel and includes session state, CSRF protection, and more.
|
*/

Route::group(['middleware' => ['web']], function () {
    //
});

I am not sure what I would use this for, or if I even need it. Can someone please explain what this is and why should/soundn't I use it?

0 likes
39 replies
DarkRoast's avatar

in 5.2 you can define groups of middleware instead of just specifying the array on your route. I guess it will save you typing out an array of middlewares for each route.

braxton's avatar

@WookieMonster I know what a Middleware group is and all of that, I am just wondering what the 'web' middleware is and what is its benefits?

1 like
alanaasmaa's avatar

I'm not really good in laravel yet byt my routes.php looks now like this:

Route::group(['middleware' => 'web'], function () {
    Route::auth();
    Route::get('/', 'PagesController@index');
    Route::get('terms-of-service', 'PagesController@terms');
    Route::get('privacy', 'PagesController@privacy');
    Route::get('combo', 'PagesController@combo');
});

If i dont add my routs and pagescontrollet to web group my auth is messing up and also error calls. Im not sure but it seems like you need to add all your sites to web middleware and some other sites to some other middleware but first try to start with web middleware.

PascalSchwientek's avatar

In 5.2 only the maintenance middleware is executed on very request. Everything else like Cookies, Sessions, CSRF was moved into the web middleware group.

Now you don't have to hack something together for you API. You just create a new middleware group and the middlewares you need. Like an JWT auth middleware.

1 like
yourlocalwebmaster's avatar

web houses the session etc, as @PascalSchwientek mentioned. I was having trouble AUTH-ing users, but when I placed my auth routes into the web middleware it worked as expected.

masterpowers's avatar

if you check the old kernel.php and the 5.2 kernel.php .. the web middleware in 5.2 refers to the old kernel of 5.1

The main point is you seperate your routing either by api middleware or web. or you can use no middleware at all.

but if your going to use any cookie, seesion or authentication you should include it inside your web middleware

1 like
michaeldyrynda's avatar

Generally speaking, an API will be stateless. This means it doesn't preserve things like sessions or cookies. Each time you make a request to an API, you'll send an authorisation token or similar, it will execute the request, and send back a response.

For a web request, you might login to the website, and the application will preserve this logged in state between routes that you visit for the duration of the session.

The API might have a throttle middleware, whilst the web application itself will require CSRF tokens, (encrypted) cookies, sessions. Now, you can apply each of those independently of each other with ease - by applying an api group middleware to your API routes and web group middleware to your web routes. If you have public routes, you can speed up the execution time of those pages by leaving out cookies and sessions entirely.

Check out Matt's blog post which goes into a bit more detail.

5 likes
toby's avatar

Is there a way to add the web middlewares to error pages w/o defining them globally?

2 likes
andremilani's avatar

Hello, I'm trying to use the middleware web, but when I put my route inside it, my project stop working. When I remove and use my route outside the middleware web, works again. What could be? (Sorry for my english, it is not my native language).

This works:

Route::get('/paginaB', 'SessaoCookiesController@paginaB');

Route::group(['middleware' => ['web']], function () {
    
});

This not works:

Route::group(['middleware' => ['web']], function () {
    Route::get('/paginaB', 'SessaoCookiesController@paginaB');
});
flamingomedia's avatar

Strange thing: in Laravel 5.2, on a fresh installation, I can see from php artisan route:list that the default / route already has the web middleware, even if it's not wrapped in the

Route::group(['middleware' => ['web']], function () {
   //
});

In fact, when I type php artisan make:auth and Laravel generates, in the routes file, the Route::group, when I do php artisan route:list I get the web middleware twice, like web, web or web, web, auth. And, by the way, with this configuration the postRegister doesn't work and just redirects me to the register page. If I take

Route::auth();

out of the web middleware, it works perfectly. I guess there's some kind of default behaviour that uses web middleware for every route, so you don't have to wrap it into the Route::group, though it's not what I can find in the documentation. Any hint?

2 likes
aardalich's avatar

I'm just noticing the same thing.

Looks like RouteServiceProvider.php has recently changed and is adding the web middleware to all routes by default.

Snapey's avatar

Taylor made a change 5 days ago to always invoke the web middleware in a RouteServiceProvider so no need to specify it in routes.php going forward.

3 likes
flamingomedia's avatar

Good news, thanks Snapey! So I guess they're going to update php artisan make:auth accordingly in the next days. Where shall I point out this issue?

kreierson's avatar

Well this makes sense now, I was having issues flashing a message to the session as I am in development on a new project. It was working fine, but then did a composer update and flash messaging broke. I removed the web middleware group in my routes file and everything is working great now.

scottjs's avatar

I've been having similar problems. I started a Laravel 5.2 project about a month ago, now I'm starting a new 5.2 project now and the same set of routes I used previously isn't working properly. I'm having difficulty authenticating users as my auth routes are wrapped in the web middleware block as with my previous project.

It looks like the users can authenticate but error messages aren't being displayed in the templates.

So does this mean there's no need to ever use:

Route::group(['middleware' => ['web']], function () {
   //
});

Within your routes again?

Snapey's avatar

@scottjs It depends exactly when you pulled the code down. The sure-fire way is to list your routes and make sure web is applied once and once only to the relevant routes.

Going forward, yes, pretend like web middleware does not exist.

rohu's avatar

To my surprise, a POST to a route in a route group with api middleware gives me a CSRF TokenMismatchException.

I try to build a sample REST API and I am using this route:

Route::group(['middleware' => 'api'], function () {
               Route::resource('/api/messages', MessagesController::class);
});

I expected this to use the api middleware only - so no CSRF checks. But - when I POST to this route I receive a TokenMismatchException and I guess that the newly re-introduced web-middleware-as-a-default is overriding my middleware somehow.

I created the project a few days ago and laravel new installed v5.2.29 for me.

Did I miss something?

1 like
novakben's avatar

I'm having the same problem as Rohu, I'm building a REST API, how can I avoid the default web group to some of my routes?

thomaskim's avatar

@rohu @novakben Open up your app/Providers/RouteServiceProvider.php file. Around line 56, remove this: 'middleware' => 'web',

Now, this means that you will also need to re-apply the web middleware on non-API routes. In order to that, open up your routes file and put those specific routes inside the web middleware group.

3 likes
rohu's avatar

OK, I'll give that a try. BUT I really liked the nice, straightforward and intuitive way it worked in the original 5.2 release:

  • Create a RESTful API -> put all API routes in a Route group using the api middleware
  • Create a Web App -> put all Web App routes in a Route group using the web middleware

All in one file, routes.php. Sweet.

Now it seems that for a RESTful API I have to tweak another file at a rather unintuitive position.

Alternatively if I put my API under /api I can tweak app/Middleware/VerifyCsrfToken.php:

    protected $except = [
        'api/*'
    ];

Again, two places to configure one thing. No real deal breaker but the original 5.2 way would match Laravels style better.

1 like
delfinet's avatar

I just got bitten by this same issue in a new app. The API calls for webhooks were failing because they were automatically loading in the web group with CSRF.

I understand wanting to make this easier for newbies, but it means that anyone developing non-trivial applications now has to remember to go and delete items from the providers and middleware.

I think that wrapping all groups in a parent group that requires CSRF is a pretty big issue, and the decision to implement that was a mistake in the long term.

WebDeveloper's avatar

We need better solution, I don't want to remember to go and delete items from the providers and middleware. I think that it will be better if they revert the change and not make web is default middleware!

1 like
Snapey's avatar

@delfinet @WebDeveloper

Isn't it just a question of commenting out line 40 of the RouteServiceProvider? It does live in your app space.

However, it would be relatively easy to make a config switch with the default to include the web route group. Perhaps you should offer a PR?

Last thing we need is a third breaking change.

davestewart's avatar

Now it seems that for a RESTful API I have to tweak another file at a rather unintuitive position.

I must admit, my first memories of learning Laravel were getting extremely frustrated at seemingly constantly discovering all the different "kinds" of places you had to edit, just to get the app running. I ended up making a list, just so the next time I set an app up, I wouldn't have the same experience:

application class

  • bootstrap/app.php

providers & aliases

  • a configuration file (config/app.php)

controller namespace

  • a protected property on RouteServiceProvider

routes

  • a require in RouteServiceProvider
  • a file in app/Http/routes.php

middleware

  • an array in app\Http\Kernel
  • and now straight PHP code in app\Providers\RouteServiceProvider

auth

  • a hardcoded a return in Auth Middleware
  • an overriden a trait in AuthController

I can't imagine the location of any of these changing until the next major release, but I didn't understand why there was such a disparity between the setup of all these. I guess once there was a critical mass of code to be run, having it all in config files made less sense.

I'd love to see some kind of FAQ / quick start section added to the docs for these kinds of common questions, to slice through all the different documentation you have to get your head round when first getting to grips with the framework.

ardf16's avatar

maybe two options: add/ override default middleware in routes.php file?

Next

Please or to participate in this conversation.