Буферизация вывода PHP, ошибка кодирования содержимого, вызванная ob_gzhandler?

Может ли кто-нибудь объяснить, почему я получаю следующую ошибку?

В коде, если echo $gz; закомментирован, я не получаю ошибки (но и нет вывода!), если это не я получаю (из Firefox),

Ошибка кодирования содержимого


Страница, которую вы пытаетесь просмотреть, не может быть показана, поскольку она использует недопустимую или неподдерживаемую форму сжатия.


Спасибо за вашу помощь, вот код:

 ob_start('ob_gzhandler') OR ob_start(); echo 'eh?'; $gz = ob_get_clean(); echo $gz; 

Вывод вашего приложения должен содержать только одну выходную кодировку. Если у вас есть несколько фрагментов, которые кодируются по-разному, то браузер получит результат, с которым невозможно работать. Следовательно, ошибка кодирования.

Сам Kohana уже использует выходной буфер. Если вы хотите совместить это с вашим выходным буфером ob_gzhandler, вам нужно запустить свой буфер до того, как кохана инициализируется. Это потому, что выходной буфер является штабелируемым. Когда кохана закончит свою буферизацию вывода, ваш будет применяться:

 ob_start('ob_gzhandler'); # your buffer: ob_starts and ends by kohana 

Поэтому всякий раз, когда kohana делает некоторый вывод, эти куски будут переданы в ваш обратный вызов ( ob_gzhandler() ) и будут закодированы в gz.

Затем браузер должен получать только gz-кодированные данные, так как это был выходной буфер на самом верхнем уровне.

Использование ob_gzhandler и ручное повторение буфера

Если вы используете ob_start('ob_gzhandler') чтобы позволить PHP работать с сжатием, а затем вы echo ob_get_clean() , вы создадите ненадежный вывод. Это связано с тем, как работает сжатие с выходной буферизацией:

PHP будет буферизовать куски вывода. Это означает, что PHP начинает сжимать вывод, но сохраняет некоторые байты для продолжения сжатия. Таким образом, ob_get_clean () возвращает так называемую сжатую часть буфера. Часто этот результат не завершен.

Чтобы справиться с этим, сначала промойте буфер:

 ob_start('ob_gzhandler') OR ob_start(); echo 'eh?'; ob_flush(); $gz = ob_get_clean(); echo $gz; 

И убедитесь, что после этого у вас больше нет выходных данных.

Если бы у вас был PHP, который дошел до конца вашего скрипта, он бы позаботился об этом: Промывка и вывод.

Теперь вам нужно вручную вызвать ob_flush() чтобы явно заставить PHP нажимать буфер через обратные вызовы.

Проверка проблем сжатия HTTP с помощью Curl

Поскольку firefox вернет ошибку, необходим другой инструмент для проверки того, что вызывает ошибку кодирования. Вы можете использовать curl чтобы отслеживать, что происходит:

 curl --compress -i URL 

Будет запрашивать URL с включенной компрессией при отображении всех заголовков ответов и неэкодированного тела. Это необходимо, так как PHP прозрачно включает / отключает сжатие обратного вызова ob_gzhandler на основе заголовков запросов.

Ответ также показывает, что PHP также установит нужные заголовки ответов. Поэтому нет необходимости указывать их вручную. Это было бы даже опасно, потому что только вызывая ob_start('ob_gzhandler') вы не можете сказать, включено ли сжатие или нет.

В случае нарушения сжатия, curl даст описание ошибки, но не отобразит тело.

Ниже приведено такое сообщение об ошибке завивки, вызванное неполностью сгенерированным результатом ошибочного сценария php:

 HTTP/1.1 200 OK X-Powered-By: PHP/5.3.6 Content-Encoding: gzip ... curl: (23) Error while processing content unencoding: invalid code lengths set 

Добавляя ключ --raw , вы можете даже пик в тело необработанного ответа:

 curl --compress --raw -i URL 

Это может создать впечатление, что происходит не так, как несжатые части тела.

Это то, что делает phpharo:

 /** output buffring */ if (isset($_SERVER['HTTP_ACCEPT_ENCODING']) && strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== false) { ob_start('ob_gzhandler'); ob_start(); } else { ob_start(); }