【发布时间】:2020-11-19 04:59:51
【问题描述】:
我将我的应用程序从 Cakephp3 升级到 cakephp4,但不幸的是,由于后勤问题,我无法相应地更新 android 应用程序。 android 应用程序使用 Content-Type application/json; charset=utf-8 进行 HTTP 调用,而 cakephp4 不断抛出错误请求。在我收集所有平板电脑并相应地更新它们之前,有没有办法让 cakephp4 接受这个标头作为权宜之计?
以下是错误日志:
1) App\Test\TestCase\Controller\Api\EmployeesControllerTest::testJwtTokenPost
Possibly related to Cake\Http\Exception\BadRequestException: "Bad Request"
#0 /var/www/html/vendor/cakephp/cakephp/src/Http/Runner.php(73): Cake\Http\Middleware\BodyParserMiddleware->process(Object(Cake\Http\ServerRequest), Object(Cake\Http\Runner))
#1 /var/www/html/vendor/cakephp/cakephp/src/Routing/Middleware/RoutingMiddleware.php(166): Cake\Http\Runner->handle(Object(Cake\Http\ServerRequest))
#2 /var/www/html/vendor/cakephp/cakephp/src/Http/Runner.php(73): Cake\Routing\Middleware\RoutingMiddleware->process(Object(Cake\Http\ServerRequest), Object(Cake\Http\Runner))
#3 /var/www/html/vendor/cakephp/cakephp/src/Routing/Middleware/AssetMiddleware.php(68): Cake\Http\Runner->handle(Object(Cake\Http\ServerRequest))
#4 /var/www/html/vendor/cakephp/cakephp/src/Http/Runner.php(73): Cake\Routing\Middleware\AssetMiddleware->process(Object(Cake\Http\ServerRequest), Object(Cake\Http\Runner))
#5 /var/www/html/vendor/cakephp/cakephp/src/Error/Middleware/ErrorHandlerMiddleware.php(121): Cake\Http\Runner->handle(Object(Cake\Http\ServerRequest))
#6 /var/www/html/vendor/cakephp/cakephp/src/Http/Runner.php(73): Cake\Error\Middleware\ErrorHandlerMiddleware->process(Object(Cake\Http\ServerRequest), Object(Cake\Http\Runner))
#7 /var/www/html/vendor/cakephp/cakephp/src/Http/Runner.php(58): Cake\Http\Runner->handle(Object(Cake\Http\ServerRequest))
#8 /var/www/html/vendor/cakephp/cakephp/src/Http/Server.php(90): Cake\Http\Runner->run(Object(Cake\Http\MiddlewareQueue), Object(Cake\Http\ServerRequest), Object(App\Application))
#9 /var/www/html/vendor/cakephp/cakephp/src/TestSuite/MiddlewareDispatcher.php(190): Cake\Http\Server->run(Object(Cake\Http\ServerRequest))
#10 /var/www/html/vendor/cakephp/cakephp/src/TestSuite/IntegrationTestTrait.php(499): Cake\TestSuite\MiddlewareDispatcher->execute(Array)
#11 /var/www/html/vendor/cakephp/cakephp/src/TestSuite/IntegrationTestTrait.php(401): App\Test\TestCase\Controller\Api\EmployeesControllerTest->_sendRequest('/api/employees/...', 'POST', Array)
#12 /var/www/html/tests/TestCase/Controller/Api/EmployeesControllerTest.php(41): App\Test\TestCase\Controller\Api\EmployeesControllerTest->post('/api/employees/...', Array)
#13 /var/www/html/vendor/phpunit/phpunit/src/Framework/TestCase.php(1415): App\Test\TestCase\Controller\Api\EmployeesControllerTest->testJwtTokenPost()
#14 /var/www/html/vendor/phpunit/phpunit/src/Framework/TestCase.php(1035): PHPUnit\Framework\TestCase->runTest()
#15 /var/www/html/vendor/phpunit/phpunit/src/Framework/TestResult.php(691): PHPUnit\Framework\TestCase->runBare()
#16 /var/www/html/vendor/phpunit/phpunit/src/Framework/TestCase.php(763): PHPUnit\Framework\TestResult->run(Object(App\Test\TestCase\Controller\Api\EmployeesControllerTest))
#17 /var/www/html/vendor/phpunit/phpunit/src/Framework/TestSuite.php(597): PHPUnit\Framework\TestCase->run(Object(PHPUnit\Framework\TestResult))
#18 /var/www/html/vendor/phpunit/phpunit/src/TextUI/TestRunner.php(627): PHPUnit\Framework\TestSuite->run(Object(PHPUnit\Framework\TestResult))
#19 /var/www/html/vendor/phpunit/phpunit/src/TextUI/Command.php(204): PHPUnit\TextUI\TestRunner->doRun(Object(PHPUnit\Framework\TestSuite), Array, Array, true)
#20 /var/www/html/vendor/phpunit/phpunit/src/TextUI/Command.php(163): PHPUnit\TextUI\Command->run(Array, true)
#21 /var/www/html/vendor/phpunit/phpunit/phpunit(61): PHPUnit\TextUI\Command::main()
#22 {main}
下面是token方法
public function token()
{
$this->getRequest()->allowMethod('post');
$employee = $this->Employees
->find()
->select(['Employees.id','Employees.project_id', 'Employees.name'])
->where(['Employees.pin_code' => $this->request->getData('pin_code')])
->firstOrFail()
->toArray();
$sites = TableRegistry::getTableLocator()->get('Sites');
$currentSite = array('id' => 0, 'name'=> 0);
$currentTransactionId = 0;
$transactions = TableRegistry::getTableLocator()->get('Transactions');
$previousTransaction = $transactions->find()->where([
'Transactions.employee_id' => $employee['id']
])->order([
'Transactions.created' => 'DESC'
])->first();
if(!empty($previousTransaction) && empty($previousTransaction->photo_out)) {
$currentSite = $sites->get($previousTransaction->site_id);
$currentTransactionId = $previousTransaction->id;
}
$this->set([
'success' => true,
'employee' => $employee,
'current_site' => $currentSite,
'sites' => $sites->find()->matching('Projects', function ($q) use ($employee) {
return $q->where(['Projects.id' => $employee["project_id"]]);
}),
'transaction_id' => $currentTransactionId,
'data' => [
'token' => JWT::encode([
'sub' => $employee['id'],
'exp' => time() + 604800
],
Security::getSalt())
],
]);
// Specify which view vars JsonView should serialize.
$this->viewBuilder()->setOption('serialize', ['success', 'employee', 'current_site', 'sites', 'transaction_id', 'data']);
}
是的,中间件是在 src/Application.php 中设置的
公共函数中间件(MiddlewareQueue $middlewareQueue): MiddlewareQueue { $中间件队列
// Catch any exceptions in the lower layers,
// and make an error page/response
->add(new ErrorHandlerMiddleware(Configure::read('Error')))
// Handle plugin/theme assets like CakePHP normally does.
->add(new AssetMiddleware([
'cacheTime' => Configure::read('Asset.cacheTime'),
]))
// Add routing middleware.
// If you have a large number of routes connected, turning on routes
// caching in production could improve performance. For that when
// creating the middleware instance specify the cache config name by
// using it's second constructor argument:
// `new RoutingMiddleware($this, '_cake_routes_')`
->add(new RoutingMiddleware($this))
// Parse various types of encoded request bodies so that they are
// available as array through $request->getData()
// https://book.cakephp.org/4/en/controllers/middleware.html#body-parser-middleware
->add(new BodyParserMiddleware())
// Cross Site Request Forgery (CSRF) Protection Middleware
// https://book.cakephp.org/4/en/controllers/middleware.html#cross-site-request-forgery-csrf-middleware
// ->add(new CsrfProtectionMiddleware([
// 'httponly' => false,
// ]))
// Add the middleware to the middleware queue
->add(new AuthenticationMiddleware($this));
return $middlewareQueue;
}
下面是测试方法
public function testJwtTokenPost() {
$this->configRequest([
'headers' => [
'Accept' => 'application/json',
'Content-Type' => 'application/json; charset=utf-8'
]
]);
// $this->enableCsrfToken();
$this->post('/api/employees/token', [
'pin_code' => '1001'
]);
$this->assertResponseOk();
$this->assertResponseContains('success');
$this->assertResponseContains('employee');
$this->assertResponseContains('current_site');
$this->assertResponseContains('transaction_id');
$this->assertResponseContains('sites');
$this->assertResponseContains('data');
}
下面是我的邮递员 json 调用
【问题讨论】:
-
请检查您的错误日志中是否存在相关错误,并将其与相关堆栈跟踪一起包含在您的问题中! PHP(不是 CakePHP)只处理表单数据,所有其他类型的数据必须手动处理,如果您没有正确设置 CakePHP 来执行此操作(Input parsing has been moved 从请求处理程序组件到正文解析器中间件),那么您可能遇到错误。
-
@ndm 更新了错误日志
-
EmployeesControllerTest::testJwtTokenPost()方法的代码是什么,您在src/Application.php中使用什么配置(如果有)设置正文解析器中间件? -
更新了@ndm 的问题。如何更新 src/Applications.php 以包含 Content-Type?
标签: json cakephp cakephp-4.x