【问题标题】:Apache ignoring PHP headers when sending a 304发送 304 时 Apache 忽略 PHP 标头
【发布时间】:2011-09-23 09:37:25
【问题描述】:

当我在 Apache + mod_php5 中设置自定义标头时,效果很好:

header('Foo: Bar');

但是当我尝试这个同时同时发送一个 304 Not Modified 响应时,标头似乎已被 apache 删除(以及 X-Powered-By 和其他标准标头)。

header('HTTP/1.1 304 No Content');
header('Foo: Bar');

有谁知道如何解决这个问题?

【问题讨论】:

  • 我不太清楚如何阅读这个RFC。难道 Apache 删除了标头以符合 RFC(并帮助缓存管理器)?也许你能理解它?
  • 我对 RFC 非常了解,而且它没有施加任何限制。它确实提到了某些标头应该在那里(主要是与缓存相关的标头)。在我的情况下,我需要添加 CORS 标头以进行跨域访问..​​
  • 试试这个而不是 2:header('Foo: Bar', true, 304);。至于“header似乎被apache删除”——你需要显示你的apache配置(httpd.conf,你的<VistualHost>以及.htaccess——这些说明可以随时随地。
  • LazyOne:尝试使用 header() 语法会导致同样的问题。至于配置,我在 Ubuntu 上使用 100% 默认配置,既不是虚拟主机也不是 .htaccess。我认为值得注意的是,甚至 X-Powered-By 也被删除了。我知道你的名字很懒,但是在你自己的系统上试试,我相信你会看到同样的东西。
  • @Evert X-Powered-By 如果 php.ini 中的 expose_php = Off 可能根本不会由 PHP 本身发送。至于 304——我重新运行了几个测试(在我最初的评论之后),是的——304 的自定义标头已被删除,但 404 和其他非 3xx 代码存在(使用 302、303、305、306 检查)。必须是特定于 304 的优化(304 = 未修改),其中响应主体必须尽可能小。

标签: php apache http http-headers


【解决方案1】:

这不能回答问题吗?

如果条件 GET 使用了强缓存验证器(请参阅第 13.3.3 节),则响应不应包含其他实体标头。否则(即条件 GET 使用弱验证器),响应不得包含其他实体标头;这可以防止缓存的实体主体和更新的标头之间的不一致。

来自http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.5

【讨论】:

  • 我不确定 CORS 标头(这是我实际尝试的)是否被视为“实体标头”,但无论如何我希望我能够添加任何其他如果我愿意,可以使用标题。具体来说,我需要 CORS 标头来避免浏览器错误。所以它没有回答问题,因为它没有解决我的问题。
  • @Evert 也许您可以更新您的问题以提及您发送的 CORS 标头(尽管我确实在 cmets 中发现了它)。还有你有什么浏览器问题?在我看来,您正在尝试做一些不应该做的事情,并且被网络服务器阻止了。
  • 它与 Firefox 5 一起使用,但这有点无关紧要。我所关心的是能够设置自定义标头,同时还发送回 304 状态代码。 HTTP 规范中没有任何内容可以阻止这一点。
  • @Evert 无法识别的标头被视为实体标头。 w3.org/Protocols/rfc2616/rfc2616-sec6.html
  • 它们可能被视为实体标头,但规范还说“应该”被删除,而不是“必须”。但除此之外,我真的不关心规范。我只是想修复我的错误;)
【解决方案2】:

从 Apache 2.4.23(据我所知,今天的最新版本)开始,当您发送 304“未修改”响应时,您将无法解决该问题,因为确实, Apache 确实明确删除了所有未列入白名单的标头:

http://svn.apache.org/viewvc/httpd/httpd/tags/2.4.23/modules/http/http_filters.c?view=markup#l1331

所以,无论我们喜欢与否(因为当我发送 304 时,我的 CORS 标头被 Apache 从响应中删除),看起来 Apache 确实遵循 RFC 建议,而且它是确实将该列表之外的所有内容都视为实体标题。

一种解决方案是修补 Apache 源代码以扩展该列表并转向将您自己开发的软件包部署到您的服务器,但这绝对不是没有其自身的一长串含义。另一方面,我听说 nginx 没有这个问题。

我提供的内容将被标准浏览器中的 WebGL 运行时使用,因此如果他们确实抱怨我的 304 响应中缺少 CORS,我将不得不将所有内容都设置为 200 OK并放弃节省的带宽。

【讨论】:

    【解决方案3】:

    我做了一个技巧来解决这个问题: 1.将所有标题放在304标题之前 2. 在发送 304 之前刷新这些标头

    header('Foo: Bar');
    flush();
    header('HTTP/1.1 304 No Content');
    

    Apache 在找到 304 之前不会删除任何标头。 我们在发送 304 之前通过 flush() 强制发送其他标头。 那个阿帕奇不能伤害我。

    【讨论】:

    • 这会导致状态 200 和“警告:无法修改标头信息 - 标头已发送”
    【解决方案4】:

    试试:

    header('Foo: bar', true, 304);
    

    【讨论】:

      猜你喜欢
      • 2017-05-29
      • 2019-04-15
      • 2015-07-29
      • 2021-01-12
      • 1970-01-01
      • 1970-01-01
      • 2017-01-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多