Тип ответа меняется с JSON на HTML без каких-либо изменений кода - PullRequest
0 голосов
/ 05 сентября 2018

У меня есть устаревшее приложение в CakePHP 2.x

У него есть метод в контроллере, который выводит JSON в такой структуре:

{"id":59,"name":"Association of Southeast Asian Nations (ASEAN)","n_grouptags":1}

Метод контроллера использовал $this->response->type('json'); для установки content-type в ответе на application/json; charset=UTF-8. Все хорошо.

Что я заметил, так это то, что если возвращаемые данные становятся больше определенной длины, content-type устанавливается на text/html; charset=UTF-8 без каких-либо изменений в коде .

Я включил несколько скриншотов ниже, которые показывают это, включая тип ответа.

Небольшой объем данных (тип содержимого = application/json - ожидается):

enter image description here

enter image description here

Дополнительные данные (тип содержимого = text/html - неожиданный):

enter image description here

enter image description here

В обоих случаях я проверил, что JSON действителен, используя https://jsonlint.com/

Почему это? Зависит ли это от длины ответа относительно того, как браузер его обрабатывает, или это проблема CakePHP?

PHP, который отвечает за вывод, выглядит следующим образом - , но в него не было внесено никаких изменений между двумя различными выходами, указанными выше :

    $this->autoRender = false; // No View (template) is associated with this

    $out = []; // Reset

    // $tags is some data from a model
    foreach ($tags as $k => $v) {
        $n_grouptags = 123; // Actual number comes from a Model 
        $out[] = ['id' => $k, 'name' => $v, 'n_grouptags' => $n_grouptags];
    }

    $this->response->type('json'); // We *want* a JSON response

    echo json_encode($out, JSON_FORCE_OBJECT); // Encode $out (the output) as JSON

Кэширование в приложении отключено: Configure::write('Cache.disable', true);

1 Ответ

0 голосов
/ 05 сентября 2018

Действия контроллера не должны отражать данные, даже если они могут работать в некоторых, может быть, даже в большинстве ситуаций. Правильный способ вывода данных, которые не основаны на визуализированном шаблоне представления, состоит в том, чтобы сконфигурировать и вернуть объект ответа (или строку, но не совместимую напрямую с 3.x) или использовать сериализованные представления.

Основная проблема не в длине содержимого, а в общем выводе данных до того, как объект ответа может отправить заголовки, что приведет к их игнорированию, это произойдет, как только будет отправлен хотя бы один байт, прежде чем отправит ответчик в игру.

Скорее всего, это происходит только определенной длины, потому что вы используете буферизацию и / или сжатие вывода PHP (см. output_buffering и zlib.output_compression в вашем php.ini), что приведет к задержке отраженных данных до тех пор, пока не будут превышены возможности хранения в буфере (в большинстве случаев это обычно 4096 байт), или буфер будет явно очищен (что произойдет автоматически в конце выполнения скрипта).

tl; dr, для быстрого исправления, настройки и возврата ответа:

$this->response->body(json_encode($out, JSON_FORCE_OBJECT));
return $this->response;

Смотри также

...