HHVM FastCGI上的Content-Length标头是间歇性的


Content-Length header on HHVM FastCGI is intermittent

也许是时差,但我没能让PHP/HHWM在我需要时给我Content-Type标头。

我已经在一台Vagrant机器上部署了完整的堆栈(MySQL、HHVM、Nginx),并在一个测试脚本上重现了这个问题:

<?php
$file='/usr/share/doc/iptables/html/NAT-HOWTO.html'; # random test file
header('Content-Length: ' . filesize($file));
echo(readfile($file));
?>

如果你用卷曲检查标题:

hostname:~ jsimpson$ curl -I http://vagrant/test.php
HTTP/1.1 200 OK
Server: nginx/1.4.6 (Ubuntu)
Date: Tue, 16 Sep 2014 22:09:25 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 2592
Connection: keep-alive
X-Powered-By: HHVM/3.2.0
Content-Encoding: none;

我们有一个内容长度标头。然而,如果我们从Chrome中找到相同的URL,并从开发工具中获得标题:

HTTP/1.1 200 OK
Server: nginx/1.4.6 (Ubuntu)
Date: Tue, 16 Sep 2014 22:14:41 GMT
Content-Type: text/html; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
X-Powered-By: HHVM/3.2.0
Content-Encoding: gzip

没有Content-Length标头。我还对此进行了数据包嗅探,以验证标头是否已发送。我可以切换到PHP FPM,它会发送头。

我用攻击服务器,重现了这个问题

curl -H 'Accept-Encoding: gzip,deflate' --compressed -v http://foo/bar

HHVM默认情况下启用压缩。禁用它让我回了头。

在将其添加到/etc/hhvm/server.ini之后,一切都非常棒

hhvm.server.gzip_compression_level = 0

我偶然发现了这个问题/特性。不过没有运行HHVM。纯nginx+PHP-FPM。问题是,如果你的PHP应用程序计算并设置Content-Lenght头字段,并且你的nginx被配置为gzip内容,它只会丢弃这些信息,并用Chunked传输编码和gzip头代替它。因此,不要将GZIP设置为非常小的缓冲区,默认值为20字节,这会产生相反的效果(最终结果比GZIP压缩前更大)。我是这样设置的:gzip_min_length 1024;