我在 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
。
这就是为什么它可以在.htaccess
vhost 的 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]