Apache 无法将重写的 URL 与常规文件匹配

Apache 无法将重写的 URL 与常规文件匹配

我已经设置了.htaccess将针对包含目录的请求重定向/htdocs/foo到文件bar.php

首先:我知道通常如何实现这一点,但由于我无法控制的原因,还想.htaccess检查 URL 是否解析为常规文件,如果不是,则重定向。

听起来不太复杂,但我无法解决这个问题。:[

这是我的.htaccess

RewriteRule ^$ http://www.example.com/foo/bar.php

RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule .* doh.php

这些规则不会重定向www.example.com/foobar.php,而是doh.php

我检查了error.log,由于某种原因,虽然文件bar.php存在,但重写条件却匹配。

RewriteCond: input='http://www.example.com/foo/bar.php' pattern='!-f' => matched

bar.php显然,如果重写的 URL 指向该文件,Apache 不会将其视为常规文件。www.example.com/foo/bar.php按预期工作。

知道原因吗?

编辑#1:

为了澄清起见,这是文件结构:

/ (File system root)
|
+ htdocs (Document root)
  |
  + foo
    |
    + .htaccess
    + bar.php
    + doh.php

编辑#2:

我正在运行 Apache 2.4。

解决方案:

预计RewriteCond包含REQUEST_FILENAME一个本地路径。由于缺少L标志,RewriteRule设置REQUEST_FILENAME为显然不是本地路径的 URL,因此测试!-f匹配。

最终,附加L标志会RewriteRule产生所需的行为:

RewriteRule ^$ http://www.example.com/foo/bar.php [L]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule .* doh.php

URL 重写后,http://www.example.com/foo/bar.php将启动一个新的流程循环,将重写的 URL 重新映射到与 的测试/htdocs/foo/bar.php不匹配的本地路径。并让其通过。:)RewriteCond!-f/htdocs/foo/bar.php

答案1

RewriteCond: input='/htdocs/foo/bar.php' pattern='!-f' => matched

不确定这是否被过度举例了,但除非有“其他事情”发生,否则根据上述指令,这并不像预期的那样。

由于您的初始(隐式)重定向缺少该L标志,因此处理将立即继续执行下一个指令。此时,我希望在日志中看到类似以下内容:

RewriteCond: input='http://www.example.com/foo/bar.php' pattern='!-f' => matched

第一个 之后RewriteRule,该REQUEST_FILENAME指令将立即更新为最后一个 的输出RewriteRulehttp://www.example.com/foo/bar.php。在此阶段,它不会重新映射到文件系统。(除非您指定了相对路径代换,在这种情况下,目录前缀将被添加 - 这看起来就像您在日志中看到的一样 - 但这与问题中的指令不对应。)

因此,上述条件确实是“匹配”——“绝对 URL”不可能作为文件系统上的文件存在。

然后你会得到一个损坏302 “重写”至doh.php。该请求是内部重写doh.php,但 HTTP 状态从之前的“重定向”设置为 302,但没有Location标头,因此没有外部重定向。(虽然您似乎暗示有一个“重定向”到doh.php?)

RewriteRule ^$ http://www.example.com/foo/bar.php

为了触发外部重定向(考虑到稍后的重写),您需要包含Llast)标志以停止当前一轮的处理。

您还应该明确地包含R标志。这里暗示了 302 重定向,因为您已在 中明确包含了方案 + 主机名RewriteRule

例如:

RewriteRule ^$ http://www.example.com/foo/bar.php [R,L]

在旁边:

这些规则不会重定向www.example.com/foo

请注意,如果您请求的/foo,不带尾随斜杠,并且/foo是一个物理目录,则 mod_dir 将首先隐式 301 重定向到,/foo/以便通过附加尾随斜杠来“修复”URL。

相关内容