我已经在 Apache 2.4.7 上设置了我的虚拟主机,配置非常简单:
<VirtualHost *:80>
ServerName foo.example.com
DocumentRoot /var/www/html
DirectoryIndex index.php
FallbackResource /index.php
</VirtualHost>
在文档根目录下我有以下结构:
/index.php
/help/readme.txt
当我发出请求时,我得到以下结果:
/bla -> 200 OK
/help/ -> 404 Not Found
/help/a -> 200 OK
似乎/help/
目录的存在导致 Apache 返回,404
因为其中没有内容index.php
,但我希望所有请求都能调用/index.php
并从而产生200 OK
响应。
我不记得在使用时这是什么问题mod_rewrite
,但FallbackResource
如果可能的话我更喜欢使用。有办法解决这个问题吗?
更新
如果我删除该DirectoryIndex
指令,它会起作用,但会受到影响五秒延迟问题。
更新 3
我正在运行以下测试环境;目录结构如下:
./htdocs
index.html
test/
bla.txt
./conf
httpd.conf
./logs
的内容httpd.conf
为:
ServerName apache-bug.local
Listen 8085
DirectoryIndex disabled
DirectorySlash Off
<VirtualHost *:8085>
DocumentRoot /home/user/apache-bug/htdocs
FallbackResource /index.html
</VirtualHost>
我的config.nice
包含:
"./configure" \
"--enable-debugger-mode" \
"--with-apr=/usr/local/apr/bin/apr-1-config" \
"--enable-dir=static" \
"--with-mpm=prefork" \
"--enable-unixd=static" \
"--enable-authn-core=static" \
"--enable-authz-core=static" \
"$@"
运行服务器:
httpd -X -d /home/user/work/apache-bug/
答案1
mod_dir.c
我也亲自回答了这个问题,因为我很确定这个问题与工作原理有关内部我认为一个错误。
如果资源无法映射到本地文件系统,则该函数fixup_dflt()
将运行,使用来FallbackResource
确定应该加载哪个文档。
然而,当资源能被映射到本地文件系统并且它是一个目录,它将尝试通过运行来解析文档fixup_dir()
;此函数迭代值列表,DirectoryIndex
直到找到第一个合适的文档。
就我而言,配置有一个空的DirectoryIndex
值列表,因此fixup_dir()
将失败并返回 404。
以下补丁对我有用(公共关系):
static int dir_fixups(request_rec *r)
{
if (r->finfo.filetype == APR_DIR) {
- return fixup_dir(r);
+ if (fixup_dir(r) != OK) {
+ /* use fallback */
+ return fixup_dflt(r);
+ }
+
+ return OK;
}
else if ((r->finfo.filetype == APR_NOFILE) && (r->handler == NULL)) {
/* No handler and nothing in the filesystem - use fallback */
return fixup_dflt(r);
}
return DECLINED;
}
它基本上是失败fixup_dflt()
后再尝试fixup_dir()
。
更新 2015-04-21
A使固定已经提交给项目,预计发布2.5版本;也可能移植到2.4版本。
更新 2015-05-18
已修复已恢复因为:
[...] 它至少会
FallBackResource
在可能发挥作用之前导致mod_autoindex
其发挥作用。
我仍在尝试找出如何避免这种情况。
答案2
你的配置应该是正确的。
奇怪的是,问题似乎是mod_deflate。
在此处成功重现您的配置后(不是出现 404 错误),我也遇到了 5 秒的延迟。但是,我注意到,当 UA 省略gzip
其 Accept-Headers 时,页面会立即显示/接收。您可以使用 亲自测试这一点wget
。
有趣的是,进一步的调试strace
表明,apache 将您的内容发送FallbackResource
到客户端的套接字,而延迟没有明显差异两个都情况。这在线上也很明显,在 HTTP 请求之后,服务器向客户端发送了一个回复包,没有任何明显的延迟1。
然而,在这种情况下使用 mod_deflate 时,UA 似乎不知道服务器发送的数据何时结束,因此在 TCP 连接超时2并被服务器强制关闭之前不会呈现任何内容。这符合 HTTP/1.0,其中关闭的连接表示内容结束。
为了HTTP/1.1,服务器有其他可用于表示内容结束的手段–但这些似乎都没有发生在这里。
但是,目前我无法确定该错误是隐藏在 mod_dir 还是 mod_deflate 中。我通过禁用 gzip 压缩使其完美运行;作为一种解决方法,在问题彻底解决之前,您可以有选择地禁用 gzip。
1 ) 这告诉我们问题不是源于服务器上未刷新的缓冲区。2
)默认情况下,apache 的超时时间为 5 秒 - 这就是 5 秒的来源。