ob_gzhandler 导致 PHP 输出缓冲、内容编码错误?

发布于 2024-11-15 22:15:02 字数 375 浏览 2 评论 0原文

谁能解释为什么我收到以下错误?

在代码中,如果 echo $gz; 被注释掉,我不会收到错误(但也没有输出!),如果不是,我会得到(来自 Firefox),

内容编码错误

<小时>

您的页面 正在尝试查看无法显示 因为它使用了无效或 不支持的压缩形式。


感谢您的帮助,代码如下:

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

Can anyone explain why I am receiving the following error?

In the code, if the echo $gz; is commented out I receive no error (but also no output!), if it isn't I get (from Firefox),

Content Encoding Error


The page you
are trying to view cannot be shown
because it uses an invalid or
unsupported form of compression.


Thanks for your help, here's the code:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

-残月青衣踏尘吟 2024-11-22 22:15:02

您的应用程序的输出应该只包含一种输出编码。如果您有多个编码不同的块,那么浏览器将得到无法处理的结果。因此出现编码错误。

Kohana 本身已经使用了输出缓冲区。如果您想将其与 ob_gzhandler 输出缓冲区结合起来,您需要在 kohana 初始化它自己的缓冲区之前启动缓冲区。那是因为输出缓冲区是可堆叠的。当 kohana 完成它的输出缓冲时,您的输出缓冲将适用:

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 通过回调推送缓冲区。

使用 Curl 检查 HTTP 压缩问题

由于 Firefox 将返回错误,因此需要另一个工具来检查导致编码错误的原因。您可以使用 curl 来跟踪发生的情况:

curl --compress -i URL

将请求启用压缩的 URL同时显示所有未编码的响应标头和正文。这是必要的,因为 PHP 根据请求标头透明地启用/禁用 ob_gzhandler 回调的压缩。

响应还表明 PHP 也会设置所需的响应标头。所以不需要手动指定它们。这甚至是危险的,因为仅通过调用 ob_start('ob_gzhandler') 您无法判断是否启用了压缩。

如果压缩被破坏,curl 将给出错误描述,但不会显示正文。

以下是由错误的 php 脚本生成的不完整输出引发的这样一条curl错误消息:

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

这可以给人留下什么印象出了问题,就像体内未压缩的部分一样。

The output of your application should only contain one output encoding. If you have multiple chunks that are encoded differently, then the browser will get a result that it is impossible to work with. Hence the encoding error.

Kohana itself makes already use of the output buffer. If you want to combine that with your ob_gzhandler output buffer, you need to start your buffer before kohana initialized it's own. That's because output buffer are stackable. When kohana has finished it's output buffering, yours will apply:

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

So whenever kohana has done some output, these chunks will get passed on into your output callback (ob_gzhandler()) and will be gz-encoded.

The browser should then only get gz-encoded data as it was the output buffer at the topmost level.

Using ob_gzhandler and manually echo'ing the buffer

If you make use of ob_start('ob_gzhandler') to let PHP deal with the compression and you then echo ob_get_clean(), you will create an unreliable output. That's related to how the compression togther with output buffering works:

PHP will buffer chunks of output. That means, PHP starts to compress the output but keeps some bytes to continue compressing. So ob_get_clean() returns the so-far compressed part of the buffer. Often that result is not complete.

To deal with that, flush the buffer first:

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

And ensure you don't have any more output after that.

If you would have PHP reached the end of your script, it would have taken care of that: Flushing and outputting.

Now you need to manually call ob_flush() to explicitly make PHP push the buffer through the callbacks.

Inspecting HTTP Compression Problems with Curl

As firefox will return an error, another tool to inspect what's causing the encoding error is needed. You can use curl to track what's going on:

curl --compress -i URL

Will request the URL with compression enabled while displaying all response headers and the body unencoded. This is necessary as PHP transparently enables / disables compression of the ob_gzhandler callback based on request headers.

A response also shows that PHP will set the needed response headers as well. So no need to specify them manually. That would be even dangerously, because only by calling ob_start('ob_gzhandler') you can not say if compression is enabled or not.

In case the compression is broken, curl will give an error description but would not display the body.

Following is such a curl error message provoked with an incompletely generated output by a faulty php script:

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

By adding the --raw switch, you can even peak into the raw response body:

curl --compress --raw -i URL

That can give an impression what's going wrong, like uncompressed parts within the body.

不即不离 2024-11-22 22:15:02

这就是 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();
}

This is what phpharo does:

/** output buffring */
if (isset($_SERVER['HTTP_ACCEPT_ENCODING']) && strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== false)
{
 ob_start('ob_gzhandler'); ob_start();
}
else
{
 ob_start();
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文