为什么Apache + Rails会为代码500吐出两个状态标头?
我有一个Rails应用程序,除了一件事以外,它都可以正常工作。
当我请求不存在的内容(即/not_a_controller_or_file.txt)并且rails抛出" No Route match ..."异常时,响应为(有意的空白行):
HTTP/1.1 200 OK Date: Thu, 02 Oct 2008 10:28:02 GMT Content-Type: text/html Content-Length: 122 Vary: Accept-Encoding Keep-Alive: timeout=15, max=100 Connection: Keep-Alive Status: 500 Internal Server Error Content-Type: text/html <html><body><h1>500 Internal Server Error</h1></body></html>
我在/ vendor中有ExceptionLogger插件,尽管这似乎不是问题。我没有在公共场合添加自定义500.html之外的任何错误处理(尽管响应中不包含该HTML),而且我不知道这部分html的来源。
因此,某处某处正在添加HTTP / 1.1 200状态代码为时过早,或者Status:500为时太晚。我怀疑它是Apache,因为使用Webrick时会得到适当的HTTP / 1.1 500标头(在顶部)。
我的生产堆栈如下:
阿帕奇2
杂种(5个实例)
RubyOnRails 2.1.1(在1.2和2.1.1中都发生)
我忘了提,该错误是由"没有路线匹配..."异常引起的
解决方案
该html文件来自Rails。它遇到某种错误(可能是某种异常,或者某些其他不可恢复的错误)。
如果在Status:标头和实际标头之间有多余的空行,而不仅仅是错字,那么这将很长的路要解释Apache为什么报告200 OK消息。
Status标头是Rails,PHP或者告诉Apache"出现错误,请返回此代码而不是200 OK"的方式。空行的事实意味着发生了一些额外的事情,并且Ruby出于某种原因在错误输出之前输出了空行。也许这是脚本的先前输出。不过,总而言之,多余的空白行表示Apache认为"哦,空白行,没有多余的标题,现在就全部内容了。",这与我们提供的Content-Length标题一致。
我的猜测是为什么以前的脚本输出是空白行,而该行可能会在完整脚本页面的结尾处结束。至于为什么发生500错误,这里没有足够的信息告诉我们。可能是文件I / O错误。
编辑:考虑到Dave提供的有关内部的额外信息,我想说这实际上是幕后发生的代理问题...我无法确切地说出什么,除了已经说过的。
这来自Rails本身。
http://github.com/rails/rails/tree/master/actionpack/lib/action_controller/dispatcher.rb#L60
调度程序将返回错误页面,状态码为200(成功)。
这是一个相当古老的线程,但值得的是,我找到了一个不错的资源,其中包括对该问题和解决方案的详细说明。显然,与Mongrel一起使用时,此错误会影响Rails <2.3.
- 这篇文章帮助我了解了问题并编写了自己的补丁。
- 包含Rails 2.2.2补丁的Rails官方故障单。