背景
我的应用程序的部分职责是以受控方式处理对静态资源(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 的作用并不大,只是设置了相关的标头并阻止了响应正文中的内容,据我所知。
更新
我刚刚注意到关于这些乱码响应的一些事情:
- 根本没有发送实际的标头,即在 Firebug 的“标头”选项卡上,对于乱码响应,它只列出请求标头,甚至不显示响应标头的标题。
- 即使我在 PHP 中的 Response 上设置了一些自定义标头,该标头也根本不会出现在乱码响应中(作为标头或响应正文中),但是对于未损坏的响应,自定义标头会正确显示。