即使目录存在,也使用 FallbackResource

Jac*_*ack 11 configuration apache-2.4

我已经使用非常基本的配置在 Apache 2.4.7 上设置了我的虚拟主机:

<VirtualHost *:80>
  ServerName foo.example.com
  DocumentRoot /var/www/html

  DirectoryIndex index.php
  FallbackResource /index.php
</VirtualHost>
Run Code Online (Sandbox Code Playgroud)

在文档根目录下,我具有以下结构:

/index.php
/help/readme.txt
Run Code Online (Sandbox Code Playgroud)

当我提出请求时,我得到以下结果:

/bla     -> 200 OK
/help/   -> 404 Not Found
/help/a  -> 200 OK
Run Code Online (Sandbox Code Playgroud)

似乎/help/目录的存在导致 Apache 返回,404因为那里没有index.php,但我希望所有请求都能调用/index.php并产生200 OK响应。

我不记得这是使用时的问题mod_rewrite,但FallbackResource如果可能的话,我更喜欢使用。有没有办法来解决这个问题?

更新

如果我删除DirectoryIndex指令,它会起作用,但是会遇到五秒延迟问题

更新 3

我正在运行以下测试环境;目录结构如下:

./htdocs
   index.html
   test/
      bla.txt
./conf
   httpd.conf
./logs
Run Code Online (Sandbox Code Playgroud)

内容httpd.conf为:

ServerName apache-bug.local
Listen 8085

DirectoryIndex disabled
DirectorySlash Off

<VirtualHost *:8085>
DocumentRoot /home/user/apache-bug/htdocs

FallbackResource /index.html
</VirtualHost>
Run Code Online (Sandbox Code Playgroud)

我的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" \
"$@"
Run Code Online (Sandbox Code Playgroud)

运行服务器:

httpd -X -d /home/user/work/apache-bug/
Run Code Online (Sandbox Code Playgroud)

Jac*_*ack 8

我自己也在回答这个问题,因为我很确定这个问题与内部的mod_dir.c工作方式有关,我认为这是一个错误

如果资源无法映射到本地文件系统,该函数fixup_dflt()将运行,使用FallbackResource来确定应该加载哪个文档。

但是,当资源可以映射到本地文件系统并且它是一个目录时,它将尝试通过运行来解析文档fixup_dir();此函数遍历DirectoryIndex值列表,直到找到第一个合适的文档。

在我的例子中,配置有一个空的DirectoryIndex值列表,所以fixup_dir()会失败并返回 404。

以下补丁对我有用PR):

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;
}
Run Code Online (Sandbox Code Playgroud)

它基本上是fixup_dflt()fixup_dir()失败后尝试。

更新 2015-04-21

一个修复已提交项目,原定于2.5; 它也可以移植到 2.4。

更新 2015-05-18

修复已被还原,因为:

[...]它[至少]导致FallBackResourcemod_autoindex可能已经启动之前启动。

我仍在努力弄清楚如何避免这种情况。


Rom*_*man 7

您的配置应该是正确的。

奇怪的是,问题似乎是mod_deflate

在此处成功复制您的配置后(没有得到 404),我也得到了 5 秒的延迟。但是,我注意到当 UAgzip从它的 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 秒的来源。