为什么apache返回一个存在的文件的404响应?

我有一个主要目的是处理RPC请求的Apache服务器。 所有这样的请求都以一个固定的前缀(比如/rpc )开头,我使用Location指令来设置这个URL的处理器(例如<Location /rpc>...</Location> )。

我现在喜欢这个服务器也提供静态文件。 我把一个index.html文件放到它的DocumentRoot但是不能让apache来为我服务。 相反,我得到404响应。 访问日志显示了这一点:

 127.0.0.1 - - [18/Aug/2010:11:41:52 -0400] "GET /index.html HTTP/1.1" 404 208 

错误日志显示这个:

 [...] [error] [client 127.0.0.1] File does not exist: /www/htdocs/index.html 

这个错误信息是一个肮脏的谎言。 我可以复制并粘贴该path并运行ls /www/htdocs/index.html ,看到该文件确实存在。

目前为止我尝试过的东西:

  • 检查文件的完整path的所有权限:所有目录是755,所有文件是644
  • 检查所有权:所有目录和文件都由apache运行的同一用户拥有
  • 设置LogLevel debug (日志中不显示新消息)
  • 添加了一个带有SetHandler default-handler指令的<Location />
  • 添加一个带有SetHandler default-handler指令的<Location /index.html>
  • 将这两个Location块移动到<Location /rpc>块的上方和下方
  • Ran dtruss并没有看到Apache在处理请求时发出一个stat()调用

我正在用尽想法。 还有什么我应该尝试?

(我在Mac OS X 10.5.8上使用apache 2.2.12,在CentOS 5.4上使用apache 2.2.3)

答案最终取决于我的问题中没有的一条信息,但是这个结果应该是一个很大的提示!

我有一个PerlMapToStorageHandler Apache2::Const::OK指令在我的Apacheconfiguration根据mod_perl文档中的build议 。 这是一个主机范围的设置,它可以防止apache在每次获取请求时调用ap_directory_walk()stat()一堆文件。 当所有的URI都是“虚拟的”(即不与磁盘上的真实文件相对应)时,这是可取的,但这也意味着你不能提供任何静态文件!

我的解决scheme是创build一个自定义的PerlMapToStorageHandler例程,避免除了我想要服务的每个文件的stat()调用:

 package MyMapToStorageHandler; use strict; use Apache2::RequestRec(); use Apache2::Const -compile => qw(DECLINED OK M_TRACE); sub handler { my $r = shift; # Fall through to the default handling for TRACE requests and requests # for the index.html file. if ($r->method_number == Apache2::Const::M_TRACE || $r->uri eq '/index.html') { return Apache2::Const::DECLINED; } # Skip ap_directory_walk stat() calls by just returning OK return Apache2::Const::OK; } 1; 

然后,在我的httpd.conf文件中,我用这个replace了现有的PerlMapToStorageHandler Apache2::Const::OK指令:

 PerlLoadModule MyMapToStorageHandler ... PerlMapToStorageHandler MyMapToStorageHandler 

那就是诀窍。