Middleware pipelines improvements - markstory/cakephp GitHub Wiki
As the first part of the middleware pipeline is now implemented, we should look on how to improve it even further. A common use case would be, to use an already registered middleware again in a more specific scope.
Following is a rough sketch on how the api for that could look like.
Router::scope('/', function (RouteBuilder $routes) {
$routes->registerMiddleware('cookie', new CookieMiddleware(/* config */));
$routes->registerMiddleware('auth', new AuthMiddleware(/* config */));
$routes->registerMiddleware('users', new UsersMiddleware(/* config */));
// Maybe middleware groups
$routes->registerMiddlewareGroup('web', ['cookie', 'auth']);
// ... or
$routes->registerMiddlewareGroup('web', [new CookieMiddleware(/* config */), new AuthMiddleware(/* config */)]);
// Apply the cookie and auth middleware to the complete `/` scope.
$routes->applyMiddleware('cookie');
$routes->applyMiddleware('auth');
$routes->scope('/api', function ($routes) {
// Apply the auth middleware to the `/api` scope but with a different config as before
$routes->applyMiddleware('auth', new AuthMiddleware(/* different config */));
// Don't use the cookie middleware for `/api`
$routes->applyMiddleware('cookie', ???);
});
// Only apply the users middleware to this route on GET requests
$routes->get('/users', ['controller' => 'users', 'action' => 'index'])->applyMiddleware('users');
// .. or apply multiple middleware at once
$routes->get('/users', ['controller' => 'users', 'action' => 'index'])->applyMiddleware('users', 'cookie');
// Maybe you want a different config for POST
$routes->post('/users', ['controller' => 'users', 'action' => 'index'])->applyMiddleware('users', new UsersMiddleware(/* different config */));
});
Another approach would be to change how middleware and scopes work. Instead of a route inheriting the middleware from each parent scope, instead routes only have middleware defined in the closest scope applied. Take the following example:
Router::scope('/', function($routes) {
$routes->applyMiddleware('one', 'two');
$routes->scope('/api', function ($routes) {
$routes->applyMiddleware('api');
$routes->get('/ping');
});
});
In the above example, the /api/ping
route would only have the 'api' middleware applied. The 'one', 'two' middleware would not be applied. This behavior allows us to remove/redefine middleware in nested scopes. Because middleware would need to be defined in nested scopes, we should also add the concept of 'middleware groups'.
Router::scope('/', function ($routes) {
// Add middleware
$routes->registerMiddleware('auth', new AuthMiddleware());
$routes->registerMiddleware('cookie', ...);
// Define the middleware groups
$routes->middlewareGroup('web', ['cookie', 'auth']);
$routes->middlewareGroup('api', ['auth.api']);
$routes->applyMiddleware('web');
$routes->scope('/api', function ($routes) {
// Apply the middleware in the api group. Web will not be applied.
$routes->applyMiddleware('api');
});
});