2

背景

我的应用程序的部分职责是以受控方式处理对静态资源(CSS、JavaScript、图像)的请求。基于一些应用程序逻辑,它会从选择的不同文件中返回一个,这些文件可能在不同时间在该 URL 上提供给不同的用户。因此,这些是静态文件,但以动态方式交付。

该应用程序基于 Symfony 组件,这些静态文件的服务由BinaryFileResponse类处理。

引导代码调用该trustXSendfileTypeHeader方法:

\Symfony\Component\HttpFoundation\BinaryFileResponse::trustXSendfileTypeHeader();

应用程序使用一些基于配置的内部逻辑以及检测和使用apache_get_modules()来确定可用性。如果XSendfile可用并且配置说要使用它,它会设置X-Sendfile-Type标题:

if ($useHeader === true) {
    $request->headers->set('X-Sendfile-Type', $header);
}
$response = new BinaryFileResponse($filename);

问题

当我将配置设置为从不使用 XSendfile 或通过 PHP 内置 Web 服务器运行此程序时,显然不支持 XSendfile,一切都很完美。

当我使用 XSendfile 时,它​​也可以工作——大多数时候。

每隔一段时间,通常如果我快速连续按 f5 键 3-4 次,“某事”就会冒出来,我得到一个乱码的响应。例如,这应该是一个 JavaScript 文件(从 Firebug 中“Net”下的“Response”选项卡复制):

hxYîãx��HTTP/1.1 200 OK 日期:2013 年 2 月 5 日星期二 14:49:10 GMT 服务器:Apache/2.2.22 (Ubuntu) X-Powered-By:PHP/5.4.6-1ubuntu1.1 缓存控制:公共上次修改时间:星期二,2013 年 1 月 29 日 13:33:23 GMT 接受范围:字节内容传输编码:二进制 ETag:“10426f-9f6-0”变化:接受编码内容编码:gzip 内容长度: 1011 Keep-Alive: timeout=5, max=98 Connection: Keep-Alive Content-Type: application/javascript

������VmoÛ6þ,ÿkÀ²ãIý°~q [Üt] XÑt¶H¤@Rv¼Àÿ}w(YS ÀØ2yïå¹*¾Á>¯¥¥,è) Æ^Ât¸BaÆ\éjgäjí Î&ð*¸Åí¸tY!³Ç$Óe"jÞ![#,n®®oï®A¨þ¸þù××Þ©¼¼ôÇêÚd¹49mv°ÔrtBÖ^;WÍÓÔg´Y¥´FéôÁR9o°35Îà^º­´N=UÐè­Eµ¢XE¸íÒ%ª°¨Úò7¬KñT¾{;£ÈrTnß³étUè{QÀçÍn·:'üJëQÍÄËZeNjOàyÕÁ:#3wö~4Òét1ù$µeN)RD| ¶FTØJ·ß½¥¨¸õGç >9TyÜxzgl-J:) b«9ûAQ½KX É!yÐÓ] óÆÎ@W¡?¢vún­·7j©ÿ¢ðõÖGEÁy\ºp¤÷cKxf?ï*¼Éç0^ïîÌÇ°ñDQ¸mYJ|4t¾ñæËۯŠ¨6:çøp(}þÑò|LÂ;Õ(#v¹* /[¨U|xª æ]ÍyìjµòÛ¯p?4sI¥"v÷ôp|uQ4ò4&Ï·$eÒc¸ xo%7Ôi´2ñx;TuÙj23 áÊ%ħ¿¹lÌwÀS.&ÏØß7¸}ó ZXzå k2'Zdùè �¦ºû-Ù[Ó²ÿU(¯¤¥=pÃjô¾ç]]Øhhô²× ÙãÚÍ4¨[!Õ}'Òþ^Ð�ûxÿ@+ÚVÞ~áÌáy?d aíD¹·U×ÃÚ] õ5íÃø¨o÷ÂAvUÆmÍaày`¦ä©A?mL[-}®(ÿË d°öò¬}Ç¢ ³Çp1À^6%0 hTô^ts´ÞíWô fO¶ö¢ÎNÜæ·HîUôÔ¶±ÌCµsxh.9åçi Û·_ÈÞØ_ÄãY_Ö}G<ì°ý2wÔ¿aw8/þù\ã±þ"0C oÂh'tE¶À¤¥7I½éßRt. s?á^d|k/Æ)wRw÷cG¿<Þ ¼´°/^ø*ʤAVZ×y¿zÅΪ¥[²Õ1ò_Vµæï_YXÁÕö ��YXÁÕö ��

注意响应正文中标头的存在,其余部分显然不是 JavaScript。开头也有一些虚假字符,这可能是导致标题被推到正文的原因。我试图确定此内容是否是 gzip 压缩的结果,但我还不能确认。(另请参阅下面的更新)

问题

首先,BinaryFileResponse甚至是用于提供文本(非二进制)文件的正确类吗?该类的文档只说“BinaryFileResponse 表示传递文件的 HTTP 响应”。这不是很详细,但它并没有说明它专门用于“二进制”文件。但是这个名字有它自己的含义,为什么 Fabien 不直接调用这个类FileResponse呢?

其次,更重要的是,这可能是什么原因造成的?我不认为这是浏览器问题,因为它在 Firefox 和 Chrome 中都是可重复的。这是 XSendfile 模块或BinaryFileResponse类中的错误吗?(我可能认为它不是前者,因为我之前以更“原始”的方式使用它,而不是通过 Symfony 组件,没有这样的问题)。

有没有其他人经历过这个?知道我应该从哪里开始寻找追踪吗?我已经查看了BinaryResponseFile源代码,但它对 XSendfile 的作用并不大,只是设置了相关的标头并阻止了响应正文中的内容,据我所知。

更新

我刚刚注意到关于这些乱码响应的一些事情:

  1. 根本没有发送实际的标头,即在 Firebug 的“标头”选项卡上,对于乱码响应,它只列出请求标头,甚至不显示响应标头的标题。
  2. 即使我在 PHP 中的 Response 上设置了一些自定义标头,该标头也根本不会出现在乱码响应中(作为标头或响应正文中),但是对于未损坏的响应,自定义标头会正确显示。
4

1 回答 1

2

首先,让我说我对这个 Apache 模块没有任何经验,但我会尝试引导您完成一般的错误推断:

您应该检查是否可以更可靠地重现它。虽然网络浏览器可能可以尝试一下,但您应该尝试curl多次执行请求,例如使用 bash for-loop。

for i in `seq 1 5`; do curl -v http://localhost/xsendfile-url; done

设置了标头并且在实际 HTTP 标头之前有一些奇怪的字符的事实使Connection: Keep-Alive我相信您将无法通过单独的curl调用重现此问题,因为它每次都会打开一个新连接。所以试试这个来检查这是否会给你带来奇怪的行为(curl 默认情况下保持活动状态):

curl -v http://localhost/xsendfile-url http://localhost/xsendfile-url http://localhost/xsendfile-url

使用它,您可以转到项目 github 问题页面并报告您的发现。他们很可能会在那里帮助您告诉您为什么 mod_xsendfile 的行为方式或您发现了错误。

于 2013-02-14T12:10:55.687 回答