从 Slim 路由中排除中间件
Excluding middleware from Slim route
根据 http://www.slimframework.com/docs/concepts/middleware.html,可以将中间件添加到应用程序、路由或组。
如何将中间件添加到所有路由(即应用程序),但将其排除在特定路由之外?
编辑。作为一种可能的解决方案,我正在考虑在我的应用程序中间件中添加一些逻辑来绕过中间件功能。使用 $request->getMethod()
获取该方法非常简单,但是,http://www.slimframework.com/docs/objects/request.html 描述的其他 URL 方法在中间件中不可用。
我认为您需要将中间件添加到路由组、示例管理路由组和用户组。
如果你想改变动态的行为,你必须修改你的中间件逻辑来检查你的特定请求,
如果客户端设置了请求类型,请对您的路线进行采样 returns JSON。
编辑:
$app = new \Slim\App();
//pass $app to middleware
$app->add(function ($request, $response, $next) use ($app) {
//do what you want with $app.
//reads config file with routes for exclude
$response = $next($request, $response);
return $response;
});
$app->get('/', function ($request, $response, $args) {
$response->getBody()->write(' Hello ');
return $response;
});
$app->run();
如果要添加全局中间件,最简单的方法如下。
$app->group('', function () {
//Add your routes here, note that it is $this->get() ... etc inside the closure
})->add(MyNewMiddlewareClass::class);
您可以通过以下方式访问中间件内部的 uri。
$uri = $request->getUri()->getPath();
有了这些信息,如果 $uri
匹配您要从中间件中排除的路径,您可以从中间件中提早 return。
我相信,在撰写本文时 post(我正在使用 Slim 3.12.1),您问题的答案是 无法从中删除之前添加的中间件一条路线.
makes middleware implementation tightly coupled with route definition. If route (or in , route name)建议的解决方案改变了,那么中间件代码也需要改变。这是因为从技术上讲,中间件并未从路由中间件堆栈中 移除。这在某些情况下会变得复杂。比如中间件是别人写的。您可能希望避免更改第三方库的代码,因此您最终可能会扩展第三方中间件以以某种方式或某种类似的解决方案覆盖其功能,但 使实现与你的路线定义.
我的建议是,与其更改中间件的逻辑以防止其对某些路由执行,不如在代码中添加逻辑以控制应将哪些中间件添加到哪些路由。 这是一个功能齐全的示例,用于演示如何将通用中间件添加到所有路由,同时仅将一些中间件添加到某些特定路由而不是全部(您打算排除的路由)。为简单起见,没有确定应将哪些中间件添加到哪些路由的逻辑,但这展示了总体思路。以下是假设:
- 以
/user
开头的路径应该受到 Authorization
中间件的保护
/user/login
和/user/signup
是例外,不需要Authentication
中间件保护。相反,我们只想允许来自特定 IP 地址的 login/signup 尝试,因此我们需要使用 IP Access Control
中间件 来保护此路由
- 对所有以
/user
开头的路径的所有请求都应使用 Logger
中间件记录(此处也不例外)
- 其他路由不需要任何中间件(所以我们应该避免使用
$app->add()
)
<?php
require __DIR__ . '/../vendor/autoload.php';
$app = new Slim\App;
// A simple middleware to write route path and middleware name
class SampleMiddleware
{
public function __construct($name)
{
$this->name = $name;
}
public function __invoke($request, $response, $next)
{
$response->write($request->getUri()->getPath() . ' invokes ' . $this->name . "\n");
return $next($request, $response);
}
}
// Three middleware instances with different names
$auth = new SampleMiddleware('Authorization');
$ipAC = new SampleMiddleware('IP Access Control');
$logger = new SampleMiddleware('Logger');
$group = $app->group('/user', function($app) {
$app->get('/profile', function($request, $response, $args){
return $response;
});
$app->get('/messages', function($request, $response, $args){
return $response;
});
})->add($auth)
->add($logger);
$group = $app->group('/user', function($app) {
$app->get('/login', function($request, $response, $args){
return $response;
});
$app->get('/signup', function($request, $response, $args){
return $response;
});
})->add($ipAC)
->add($logger);
$app->get('{p:.*}', function($request, $response, $args){
$response->write('No middleware for ' . $request->getUri()->getPath());
return $response;
});
$app->run();
输出:
/user/profile
/user/profile invokes Logger
/user/profile invokes Authorization
/user/login
/user/login invokes Logger
/user/login invokes IP Access Control
/something/else
No middleware for /something/else
根据 http://www.slimframework.com/docs/concepts/middleware.html,可以将中间件添加到应用程序、路由或组。
如何将中间件添加到所有路由(即应用程序),但将其排除在特定路由之外?
编辑。作为一种可能的解决方案,我正在考虑在我的应用程序中间件中添加一些逻辑来绕过中间件功能。使用 $request->getMethod()
获取该方法非常简单,但是,http://www.slimframework.com/docs/objects/request.html 描述的其他 URL 方法在中间件中不可用。
我认为您需要将中间件添加到路由组、示例管理路由组和用户组。 如果你想改变动态的行为,你必须修改你的中间件逻辑来检查你的特定请求, 如果客户端设置了请求类型,请对您的路线进行采样 returns JSON。
编辑:
$app = new \Slim\App();
//pass $app to middleware
$app->add(function ($request, $response, $next) use ($app) {
//do what you want with $app.
//reads config file with routes for exclude
$response = $next($request, $response);
return $response;
});
$app->get('/', function ($request, $response, $args) {
$response->getBody()->write(' Hello ');
return $response;
});
$app->run();
如果要添加全局中间件,最简单的方法如下。
$app->group('', function () {
//Add your routes here, note that it is $this->get() ... etc inside the closure
})->add(MyNewMiddlewareClass::class);
您可以通过以下方式访问中间件内部的 uri。
$uri = $request->getUri()->getPath();
有了这些信息,如果 $uri
匹配您要从中间件中排除的路径,您可以从中间件中提早 return。
我相信,在撰写本文时 post(我正在使用 Slim 3.12.1),您问题的答案是 无法从中删除之前添加的中间件一条路线.
我的建议是,与其更改中间件的逻辑以防止其对某些路由执行,不如在代码中添加逻辑以控制应将哪些中间件添加到哪些路由。 这是一个功能齐全的示例,用于演示如何将通用中间件添加到所有路由,同时仅将一些中间件添加到某些特定路由而不是全部(您打算排除的路由)。为简单起见,没有确定应将哪些中间件添加到哪些路由的逻辑,但这展示了总体思路。以下是假设:
- 以
/user
开头的路径应该受到Authorization
中间件的保护 /user/login
和/user/signup
是例外,不需要Authentication
中间件保护。相反,我们只想允许来自特定 IP 地址的 login/signup 尝试,因此我们需要使用IP Access Control
中间件 来保护此路由
- 对所有以
/user
开头的路径的所有请求都应使用Logger
中间件记录(此处也不例外) - 其他路由不需要任何中间件(所以我们应该避免使用
$app->add()
)
<?php
require __DIR__ . '/../vendor/autoload.php';
$app = new Slim\App;
// A simple middleware to write route path and middleware name
class SampleMiddleware
{
public function __construct($name)
{
$this->name = $name;
}
public function __invoke($request, $response, $next)
{
$response->write($request->getUri()->getPath() . ' invokes ' . $this->name . "\n");
return $next($request, $response);
}
}
// Three middleware instances with different names
$auth = new SampleMiddleware('Authorization');
$ipAC = new SampleMiddleware('IP Access Control');
$logger = new SampleMiddleware('Logger');
$group = $app->group('/user', function($app) {
$app->get('/profile', function($request, $response, $args){
return $response;
});
$app->get('/messages', function($request, $response, $args){
return $response;
});
})->add($auth)
->add($logger);
$group = $app->group('/user', function($app) {
$app->get('/login', function($request, $response, $args){
return $response;
});
$app->get('/signup', function($request, $response, $args){
return $response;
});
})->add($ipAC)
->add($logger);
$app->get('{p:.*}', function($request, $response, $args){
$response->write('No middleware for ' . $request->getUri()->getPath());
return $response;
});
$app->run();
输出:
/user/profile
/user/profile invokes Logger
/user/profile invokes Authorization
/user/login
/user/login invokes Logger
/user/login invokes IP Access Control
/something/else
No middleware for /something/else