Understanding Laravel Middleware with example

Understanding Laravel Middleware with example 

Laravel Middleware

Before jumping into details of Laravel Middleware, Lets quickly recap and understand how Laravel Request Lifecycle works?

Each and every HTTP request coming into a Laravel application is converted into an Illuminate Request object, which then passes through all middleware, and is processed by the application. The application generates a response object, which is then passed back through all of the middleware (in reverse order) and returned to the end-user.

Introduction – What is Laravel Middleware?

Laravel middleware acts as an intermediate between HTTP requests and the application, i.e filter the incoming requests before entering into the main application logic. It facilitates the developers to provide an extra level of authentication and security before the HTTP request
enters into the application logic.

 

Laravel Middleware or HTTP middleware is one of the most popular features from Laravel 5 onwards. The basic concept behind is that laravel middleware is a series of layers wrapping around your laravel application, like a multilayer cake or an onion. As shown in the below diagram: every HTTP request passes through every middleware layer on its way into the application, and then the resulting response passes back through the middleware layers on its way out to the end-user.

Why do we need middleware in Laravel?

What happens when a user requests a web page using a browser? Whenever a user requests a web page, the client browser sends the request to a web server and the server responds. Sometimes, this request-response mechanism is simple and sometimes it is fairly complicated. But at the end of the day whenever a user requests for a page an HTTP request enters your application. Most of the time it is innocuous, but as the proverb goes you cannot and should not rely on the user’s input or request so it needs to filter. It has to be filtered when your application needs an extra bit of authentication or security measures to be taken. Middleware does this out of the box.

By the end of this article, you should be able to create middleware, registers it and use it in your projects.
We will be illustrating the creation till usage of middlewares by creating one of our own.

Laravel in-built middlewares

Laravel framework comes with several middleware, including middlewares for – authentication and CSRF protection.
The default middleware is located in the app/Http/Middleware directory.

You can also read the Laravel Middleware guide from Laravel’s official documentation here.

Important Points about Laravel Middleware

The following are a few scenarios where Laravel middleware can be useful:

  • Filtering the incoming HTTP request and manipulating the responses.
  • Verify whether the user authenticated or not.
  • Middleware can inspect a request and decorate it, or reject it, based on what it finds
  • Middleware not only adds extra security to your application but also gives you enough freedom to create your own
    security mechanism alongside the default Laravel Authentication mechanism
  • Middleware is most often considered separate from your application logic
  • Logging of incoming HTTP requests.
  • Redirecting the users based on requests.

TIP – The default Auth middleware is also used to protect the routes from unauthorized users.

This can be achieved by applying an auth middleware to a group of routes:

/* All Authenticated routes here */
Route::group(array('middleware' => 'auth'), function() {
Route::get('/get_store_vendors', 'WarehouseVendorsController@getStoreVendors');
Route::post('/add_store_vendor', 'WarehouseVendorsController@addStoreVendors');
Route::post('/make_vendor_payment', 'WarehouseVendorsController@makeVendorPayment');

});

Website Development Company in Ghaziabad

How to create middleware in Laravel?

In addition to in-built middlewares, Laravel allows developers to create and define custom middlewares, register them and, finally attach them to routes.

Suppose, we want to create a middleware that rejects every request that uses the DELETE HTTP method, and also sends a cookie back for every request. The following “Laravel Artisan Commands” can be used to create new middleware:

                   php artisan make:middleware BanDeleteMethod

This command will create new file at app/Http/Middleware/BanDeleteMethod.php.

<?php

namespace App\Http\Middleware;
use Closure;

class BanDeleteMethod
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
// At this point, $request is the raw request from the user.
// Test for the DELETE method
if ($request->method() === 'DELETE') {
return response("Get out of here with that delete method",405 );
}

// Now we've decided to accept it. Let's pass it on to the next
// middleware in the stack. We pass it to $next(), and what is
// returned is the response after the $request has been passed
// down the stack of middleware to the application and the
// application's response has been passed back up the stack.

return $next($request);
}
}

Using this middleware, we will only allow access to the route if the incoming HTTP request is not DELETE Method. If its delete method, we will redirect the users back to the home URI.

Understanding middleware’s handle() method

First, remember that middleware are layered one on top of another, and then finally on top of the app. The first middleware that’s registered gets first access to a request when it comes in, then that request is passed to every other middleware in turn, then to the app; then the resulting response is passed outward through the middleware, and finally this first middleware gets last access to the response when it goes out.

Interesting point to note that handle() method is used in both cases while receiving incomming request and sending back
responses().

Let’s imagine we’ve registered BanDeleteMethod as the first middleware to run. That means the $request coming into it is the raw request, unadulterated by any other middleware. Then, What?

What is $next($request)?

Passing that request to $next() means handing it off to the rest of the middleware. The $next() closure just takes that $request and passes it to the handle() method of the next middleware in the stack. It then gets passed on down the line until there is no more middleware to hand it to, and it finally ends up at the application. The application returns a response, which is passed back up the chain of middleware—because each middleware returns its response.

 

TIP – It’s best to envision middleware as a series of “layers” HTTP requests must pass through before they hit your application. Each layer can examine the request and even reject it entirely.

Registering or Binding Laravel Middleware

So far, We have just defined our own middle. The next task is to bind/register that middleware to Kernel. We need to register this middleware to the Laravel framework. Developer defined middleware can be registered in two ways:

  • Globally – Global Middleware
  • Assigning middleware to specific routes.

Registering/Binding Global Middleware

Global middleware is applied to every route; route middleware is applied on a route-by-route basis. If you want a middleware to run during every HTTP request to your application, list the middleware class in the $middleware property of your app/Http/Kernel.php class.

Below is an example of Binding global middleware:

// app/Http/Kernel.php
protected $middleware = [
\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
\App\Http\Middleware\BanDeleteMethod::class,
];

Attaching middleware to specific routes:

You can also assign Middleware to specific routes added as a route middleware or as part of a middleware group.

In the app/Http/Kernel.php – By default, the $routeMiddleware property of this class contains entries for the middleware included with Laravel. To add your own, append it to this list and assign it a key of your choosing:

Example – Binding route middleware

// app/Http/Kernel.php
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
...
'nodelete' => \App\Http\Middleware\BanDeleteMethod::class,
];

Using Laravel Middleware in Route definitions

Example – Applying route middleware in route definitions

// Doesn't make much sense for our current example...
Route::get('contacts', [
'middleware' => 'nodelete',
'uses' => 'ContactsController@index'
]);
// Makes more sense for our current example...
Route::group(['prefix' => 'api', 'middleware' => 'nodelete'], function () {
// All routes related to an API
});

Assign multiple middlewares to the route

We can assign more than one middleware to a specific route:

Route::get('/', function () {
//
})->middleware('first', 'second');

Passing Parameters to Laravel Middleware

you can pass parameters to a route middleware. Middleware can also receive additional parameters. For example, if your application needs to verify that the authenticated user has a given “role” before performing a given action, you could create a CheckRole middleware that receives a role name as an additional argument.

To achieve this, Additional middleware parameters will be passed to the middleware after the $next argument:

For example, you might have an authentication middleware that will act differently depending on whether you’re guarding for the member user type or the owner user type:

Route::get('company', function () {
return view('company.admin');
})->middleware('auth:owner');

To make this work, you’ll need to add one or more parameters to the middleware’s handle() method, and update that method’s logic accordingly:

public function handle($request, $next, $role)
{
   if (auth()->check() && auth()->user()->hasRole($role)) {
   return $next($request);
   }

   return redirect('login');
}

What is Terminable Middleware in Laravel?

Sometimes a middleware may need to do some work after the HTTP response has been prepared. For example, the “session” middleware included with Laravel writes the session data to storage after the response has been fully prepared. If you define a terminate method on your middleware, it will automatically be called after the response is ready to be sent to the browser.

<?php

namespace Illuminate\Session\Middleware;
use Closure;

class StartSession
{
    public function handle($request, Closure $next)
    {
        return $next($request);
    }

    public function terminate($request, $response)
    {
        // Store the session data...
    }
}

Here, the terminate method should receive both the request and the response. Once you have defined a terminable middleware, you should add it to the list of the route or global middleware in the app/Http/Kernel.php file.

Conclusion!

Good! Now that we have learned all about Laravel Middleware. Finally, we can conclude that Middleware wraps the application and can reject or decorate any request and response.

Further reading:

1 Comment

Leave a Reply

Your email address will not be published. Required fields are marked *