Lumen middleware pipeline execution order in grouped routes
0 reputation · 29 Jul 2023, 12:36 UTC
0 reputation · 29 Jul 2023, 12:36 UTC
Lumen utilizes a FastRoute implementation and a middleware pipeline to filter incoming HTTP requests. When organizing an API, routes are often grouped to share common attributes, such as prefixes or specific middleware layers.
There is a need to determine the exact execution sequence when a request matches a route that is subject to both global middleware (defined in bootstrap/app.php) and route-specific middleware assigned via a group. It is unclear if the framework allows for a configurable priority between these two layers or if the global stack always precedes the group stack regardless of the registration order.
Does the Lumen middleware pipeline execute global middleware before group-specific middleware in all scenarios? Is there a mechanism to inject a group-level middleware before the global stack?
34275 reputation · 30 Jul 2023, 00:01 UTC
In Lumen, global middleware registered in bootstrap/app.php runs before route-group middleware. The framework does not provide a built-in priority mechanism to inject group-level middleware ahead of the global stack. The layering is fixed: global middleware executes first, then group middleware, then the route handler.
$app->middleware([...]) in bootstrap/app.php and applies to every request.$app->group(['middleware' => ['auth']], function () { ... });.$next($request) stops the pipeline.Create a global middleware that tags the response:
<?php
namespace App\Http\Middleware;
use Closure;
class GlobalMarker
{
public function handle($request, Closure $next)
{
$response = $next($request);
$response->headers->set('X-Global', 'true');
return $response;
}
}
Register it in bootstrap/app.php:
$app->middleware([
App\Http\Middleware\GlobalMarker::class,
]);
Create a group middleware:
<?php
namespace App\Http\Middleware;
use Closure;
class GroupMarker
{
public function handle($request, Closure $next)
{
$response = $next($request);
$response->headers->set('X-Group', 'true');
return $response;
}
}
Define a group:
$app->group(['prefix' => 'api', 'middleware' => [App\Http\Middleware\GroupMarker::class]], function () {
$app->get('/test', function () {
return 'ok';
});
});
Request /api/test and inspect headers. The global marker should appear before the group marker. If the order differs, check whether a global middleware short-circuits the pipeline.
Do any of your global middleware conditionally return a response without calling $next($request)? That would prevent group middleware from running and could explain an unexpected sequence.
Use comments to ask for clarification. Post a solution as an answer.
5,310 reputation · 29 Jul 2023, 19:34 UTC
Lumen processes middleware in a fixed linear sequence: global middleware (registered via $app->middleware() in bootstrap/app.php) executes first for every request, followed by group middleware, then route-specific middleware. The router only applies group/route middleware after it has matched the request, which occurs after the global stack has already run.
There is no configuration flag or registration order that allows group middleware to precede the global stack. If you need authentication logic to run before certain global middleware (e.g., logging), you must either move that logic into the global stack with explicit ordering or handle it inside the global middleware itself via conditional checks.
To verify the order in your own codebase, add a temporary middleware that writes a distinct log entry at each layer (global, group, route) and inspect the log sequence for a single request.