mod_rewrite REQUEST_FILENAME 不包含绝对路径

mod_rewrite REQUEST_FILENAME 不包含绝对路径

我在 mod_rewrite RewriteCond 条目中测试文件是否存在的测试操作时遇到了问题%{REQUEST_FILENAME}。似乎%{REQUEST_FILENAME}我得到的不是绝对路径,而是根植于的路径DocumentRoot

配置

<VirtualHost>我的 apache 2.2.9 配置中的一个块中有这个:

RewriteEngine on
RewriteLog /tmp/rewrite.log
RewriteLogLevel 5

#push virtually everything through our dispatcher script
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^/([^/]*)/?([^/]*) /dispatch.php?_c=$1&_m=$2 [qsa,L]

尝试诊断

该规则是一种很常见的习惯用法,用于通过脚本路由不存在的文件或目录的请求。问题是,即使文件存在。

如果我删除该规则,我可以正常请求普通文件。但是,有了该规则,这些请求将被定向到 dispatch.php。

重写日志跟踪

这是我在 rewrite.log 中看到的内容

init rewrite engine with requested uri /test.txt
applying pattern '^/([^/]*)/?([^/]*)' to uri '/test.txt'
RewriteCond: input='/test.txt' pattern='!-f' => matched
RewriteCond: input='/test.txt' pattern='!-d' => matched
rewrite '/test.txt' -> '/dispatch.php?_c=test.txt&_m='
split uri=/dispatch.php?_c=test.txt&_m= -> uri=/dispatch.php, args=_c=test.txt&_m=
local path result: /dispatch.php
prefixed with document_root to /path/to/my/public_html/dispatch.php
go-ahead with /path/to/my/public_html/dispatch.php [OK]

因此,在我看来,REQUEST_FILENAME 被呈现为来自文档根目录而不是文件系统根目录的路径,这大概就是文件测试操作员失败的原因。

任何解决此问题的指示都非常感谢...

答案1

我也花了一段时间才找到原因,mod_rewrite 文档

REQUEST_FILENAME 与请求匹配的文件或脚本的完整本地文件系统路径(如果服务器当时已经确定了该路径)REQUEST_FILENAME。否则,例如在虚拟主机上下文,与 的值相同REQUEST_URI

这就是为什么它可以在.htaccessvhost 的 conf 文件中工作,但在 vhost 的 conf 文件中却不行的原因。(这也是为什么添加可以DOCUMENT_ROOT解决问题的原因)。

答案2

我通过将文档根目录明确写入条件来解决这个问题

RewriteCond /path/to/my/public_html%{REQUEST_FILENAME} !-f
RewriteCond /path/to/my/public_html%{REQUEST_FILENAME} !-d

答案3

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

这不会按预期发挥作用虚拟主机(或者服务器) 上下文,因为指令是在请求映射到文件系统之前处理的,这与在目录(或.htaccess)上下文。在请求映射到文件系统之前,REQUEST_FILENAME与 相同REQUEST_URI,即相对于根的 URL 路径。

不过,您可以使用前瞻来获取请求最终将映射到的绝对文件名。例如:

RewriteCond %{LA-U:REQUEST_FILENAME} !-f
RewriteCond %{LA-U:REQUEST_FILENAME} !-d

DOCUMENT_ROOT或者,从and (根目录相对 URL 路径)构建绝对文件名REQUEST_URI。例如:

RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-f
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-d

答案4

RewriteCond     %{REQUEST_URI}     ^(/pathinfo/|/pathinfo)(.*)$
RewriteRule     .*          %{DOCUMENT_ROOT}%{REQUEST_URI} [L]

相关内容