Cakephp4 don';t接受内容类型application/json;字符集=utf-8

Cakephp4 don';t接受内容类型application/json;字符集=utf-8,json,cakephp,cakephp-4.x,Json,Cakephp,Cakephp 4.x,我将我的应用程序从Cakephp3升级到cakephp4,但不幸的是,由于逻辑问题,我无法相应地更新android应用程序。android应用程序使用内容类型application/json进行HTTP调用;charset=utf-8和cakephp4不断抛出错误请求。在我收集所有平板电脑并进行相应更新之前,是否有办法让cakephp4接受此标题作为权宜之计 以下是错误日志: 1) App\Test\TestCase\Controller\Api\EmployeesControllerTest:

我将我的应用程序从Cakephp3升级到cakephp4,但不幸的是,由于逻辑问题,我无法相应地更新android应用程序。android应用程序使用内容类型
application/json进行HTTP调用;charset=utf-8
和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}
下面是令牌方法

  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 { $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呼叫


在测试非
应用程序/x-www-form-urlencoded
请求时,必须将数据作为字符串传递,因为测试用例无法可靠地假设如何可能将数据转换为字符串本身

即,将JSON字符串作为POST数据传递,而不是数组,字符串是PHP为实际HTTP请求公开
application/JSON
数据的方式:

$this->post('/api/employees/token',json\u encode([
“pin_代码”=>“1001”
]));

无需为此进一步配置,它支持JSON开箱即用。

请检查相关错误的错误日志,并将其与相关stacktrace一起包含在您的问题中!PHP(不是CakePHP)只处理表单数据,所有其他类型的数据都必须手动处理,如果您没有正确设置CakePHP(从请求处理程序组件到主体解析器中间件),那么您可能会遇到错误。@ndm用错误日志更新。
EmployeesControllerTest::testJwtTokenPost()的代码是什么
方法,以及在
src/Application.php
中使用什么配置(如果有)设置主体解析器中间件?更新了问题@ndm。如何更新src/Applications.php以包含内容类型?不幸的是,这不是我想要的答案,因为我不想更改单元测试。我为客户安装的android应用程序不容易更新,而且它们有这个标题。对我来说,让cakephp服务器接受该标题比更改400多个平板电脑更容易。@mosesliagz您需要提供更多的信息。您是否试图说您的Android应用程序正在发送
application/x-www-form-urlend
格式的数据以及
内容类型:application/json
标题?请在您的问题中添加详细信息,以了解Android应用程序的实际HTTP请求是什么样子的(标题和数据/正文)!我的android应用程序正在尝试发送标题
内容类型:application/json;charset=utf-8
而该字符集正是导致问题的原因。@MosesLiaoGZ我非常确定该字符集不会导致您在问题中显示的错误(假设您使用的是最新的CakePHP版本)。主体解析器中间件将只使用第一个
之前的字符串,如果它无法从标头获取注册类型,它甚至无法引发该异常。同样,请显示有问题的HTTP请求的确切外观,并包括相关错误(不是测试用例触发的错误!)。我做了一个屏幕截图,它通过postman抛出错误400。我用截图更新了这个问题