php - 添加中间件时执行两次动作 Slim 框架
问题描述
我正在基于优秀的 Slim 4 教程https://odan.github.io/2019/11/05/slim4-tutorial.html构建一个简单的应用程序
结构仍然与教程非常相似。
每次我使用 Postman 调用我的任何端点时,它都会为 Get 执行两次我的操作(即:\App\Action\UserGetAction)。我可以在我的日志中确认这正在发生。
如果我注释掉 config/middleware.php 中的 AuthMiddleware 文件,则重复操作将停止发生。
有任何想法吗?
我创建了自己的 Auth 中间件并将其添加到 config/middleware.php 文件中:
use Selective\BasePath\BasePathMiddleware;
use Slim\App;
use Slim\Middleware\ErrorMiddleware;
use SlimSession\Helper;
use App\Factory\SessionFactory;
use App\Factory\AuthMiddleware;
return function (App $app) {
// Parse json, form data and xml
$app->addBodyParsingMiddleware();
// Add the Slim built-in routing middleware
$app->addRoutingMiddleware();
$app->add(BasePathMiddleware::class);
// Catch exceptions and errors
$app->add(ErrorMiddleware::class);
$app->add(AuthMiddleware::class); // <--- here
$loggerFactory = $app->getContainer()->get(\App\Factory\LoggerFactory::class);
$logger = $loggerFactory->addFileHandler('error.log')->createInstance('error');
$errorMiddleware = $app->addErrorMiddleware(true, true, true, $logger);
};
为简单起见,我已经删除了 AuthMiddleware 中的几乎所有内容:
namespace App\Factory;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\RequestHandlerInterface as RequestHandler;
use Slim\Psr7\Response;
use GuzzleHttp\Client;
use Exception;
use App\Factory\LoggerFactory;
class AuthMiddleware
{
/**
* @var LoggerInterface
*/
private $logger;
public function __construct(LoggerFactory $logger)
{
$this->logger = $logger
->addFileHandler('user_edit.log')
->addConsoleHandler()
->createInstance('user_edit');
}
/**
* Example middleware invokable class
*
* @param ServerRequest $request PSR-7 request
* @param RequestHandler $handler PSR-15 request handler
*
* @return Response
*/
public function __invoke(Request $request, RequestHandler $handler): Response
{
$response = $handler->handle($request);
$headers = $request->getHeaders();
$eauth = $headers["Authorization"][0];
$this->logger->info($eauth);
return $handler->handle($request);
}
} //Class
这是我在 config/routes.php 中的路线:
$app->post('/users', \App\Action\UserCreateAction::class);
$app->map(['PUT', 'PATCH'],'/users/{id}[/{system}]', \App\Action\UserUpdateAction::class);
$app->delete('/users/{id}[/{system}]', \App\Action\UserDeleteAction::class);
$app->get('/users/{id}[/{system}]', \App\Action\UserGetAction::class);
$app->get('/extid/{id}[/{system}]', \App\Action\ExtidGetAction::class);
我已经确认我只运行 $app-run() 一次 --- 在我的 index.php 末尾
require __DIR__ . '/../config/bootstrap.php';
$app->run();
解决方案
__invoke
您的中间件方法有错误。
您两次调用处理程序队列:
public function __invoke(Request $request, RequestHandler $handler): Response
{
// here you call handler queue first time
// so you get response
$response = $handler->handle($request);
$headers = $request->getHeaders();
$eauth = $headers["Authorization"][0];
$this->logger->info($eauth);
// here you call handle queue for the second time
// so you get the second duplicated version of response
// this is the reason why you actions called twice
return $handler->handle($request);
}
解决方案之一如下:
public function __invoke(Request $request, RequestHandler $handler): Response
{
// here you call handler queue first time
// so you get response
$response = $handler->handle($request);
$headers = $request->getHeaders();
$eauth = $headers["Authorization"][0];
$this->logger->info($eauth);
// return response you already have
return $response;
}
推荐阅读
- flutter - Flutter PageView 无法正常工作
- javascript - 如何使用 selenium 从 iframe 元素中获取标题?
- java - 如何在java中将地图转换为实体对象?
- sql - SQL如何仅在满足两个条件时排除行
- r - 谁能帮我在不使用日期格式的情况下将我的数据框转换为时间序列对象?
- flutter - Flutter JWT 令牌自动刷新
- mysql - 为了工作,我的 CREATE TABLE 中缺少什么?mysql 8.X
- html - HTML/CSS 将图标放在密码输入字段中
- github - GitHub 组织从一家公司转移到另一家拥有所有存储库的公司
- node.js - 向 Socket.io 中的其他房间发送消息