Mastering Laravel Middleware: Pre and Post Request Processing
When building web applications with Laravel, controlling the flow of HTTP requests is crucial. Laravel's middleware provides a powerful mechanism to filter and manipulate HTTP requests entering your application. In this post, we'll dive deep into how you can leverage middleware for both pre and post-request processing.
Understanding Laravel Middleware
Middleware acts as a convenient mechanism for filtering HTTP requests entering your application. Think of it as a series of layers that the request must pass through before it reaches your application's core.
Types of Middleware
Laravel allows you to create two types of middleware:
- Before Middleware: Executes tasks before the request is handled by the application.
- After Middleware: Performs operations after the application has processed the request.
Let's look at examples of both types:
Before Middleware
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class BeforeMiddleware
{
public function handle(Request $request, Closure $next): Response
{
// Perform action before the request is handled
$request->headers->set('X-Track-Id', uniqid());
return $next($request);
}
}
In this example, the middleware adds a tracking ID to the request headers before passing it further down the application stack.
After Middleware
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class AfterMiddleware
{
public function handle(Request $request, Closure $next): Response
{
$response = $next($request);
// Perform action after the request is handled
$response->headers->set('X-Track-Id', $request->header('X-Track-Id'));
return $response;
}
}
This middleware captures the response, adds the tracking ID from the request to the response headers, and then returns the response.
Real-Life Example
Let's consider a scenario where we want to track the processing time of each request in our application. We can use a combination of Before and After middleware to achieve this.
First, let's create a TrackRequestTime
middleware:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class TrackRequestTime
{
public function handle(Request $request, Closure $next): Response
{
$request->attributes->set('start_time', microtime(true));
$response = $next($request);
$duration = microtime(true) - $request->attributes->get('start_time');
$response->headers->set('X-Request-Duration', round($duration * 1000, 2) . 'ms');
return $response;
}
}
Now, let's apply this middleware to a route:
Route::get('/api/users', function () {
// Simulate some processing time
sleep(1);
return User::all();
})->middleware(TrackRequestTime::class);
When we make a request to this route, the middleware will:
- Set a start time before the request is processed
- Allow the request to be handled by the application
- Calculate the duration after the response is generated
- Add the duration to the response headers
The output will look something like this:
// Response headers
{
"X-Request-Duration": "1002.45ms"
}
// Response body
[
{
"id": 1,
"name": "John Doe",
"email": "john@example.com"
},
{
"id": 2,
"name": "Jane Doe",
"email": "jane@example.com"
}
]
If you found this guide helpful, don't forget to subscribe to my daily newsletter and follow me on X/Twitter for more Laravel tips and tricks!