RewriteCond奇怪的行为(文件存在检查)

ink*_*ink 1 apache .htaccess mod-rewrite

我无法理解为什么重定向依赖于RewriteRule(而不是RewriteCond).

我的.htaccess:

Options +FollowSymLinks +SymLinksIfOwnerMatch

<IfModule mod_rewrite.c>
RewriteEngine on

RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^(.*)$ true.txt

RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ false.txt
</IfModule>
Run Code Online (Sandbox Code Playgroud)

根文件夹包含:

true.txt(包含'true')
false.txt(包含'false')
test.txt(包含'test')

如果我试图打开,test.txt我会得到true,如果我试图打开,nonexist.txttrue也会得到.

现在我改变了我的.htaccess:

...
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^(.*)$ $1
...
Run Code Online (Sandbox Code Playgroud)

现在,如果我尝试打开,test.txt我会得到test,如果我试图打开nonexist.txt我得到false.

更新:感谢您的回答,我理解它是如何工作的,但仍然存在一个问题.如果我尝试在另一个目录中检查'if file exists',它总是会返回false.

/files/test.txt
/script/.htaccess
/script/false.txt
/script/true.txt

现在我的.htaccess看起来像

RewriteCond %{REQUEST_FILENAME} .*(true|false).*$
RewriteRule .* - [S=2]

RewriteCond %{DOCUMENT_ROOT}/files/%{REQUEST_FILENAME} -f
RewriteRule ^(.*)$ true.txt [L]

RewriteCond %{DOCUMENT_ROOT}/files/%{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ false.txt [L]
Run Code Online (Sandbox Code Playgroud)

我总是得到false.我也试过RewriteCond ../files/%{REQUEST_FILENAME},也总是得到false结果.

如果我移动test.txtscript文件夹,然后,改变RewriteCond %{REQUEST_FILENAME}一切工作正常.

SáT*_*SáT 7

这是因为mod_rewrite的工作方式:用户请求test.txt,mod_rewrite捕获请求并将URI重写为false.txt,然后通过发送false.txt的内部请求进行第二次传递,该请求被捕获并重写到true.txt.然后进行第三次传递,捕获请求并将其重写为true.txt,但由于URI保持不变,因此不再进行传递.

这是违反直觉的,但它有逻辑.这是文档的控制流程图:

控制mod_rewrite的流程图

[L]标志通常被宣传为停止递归的魔术子弹,但实际上它只是确保一旦请求与模式匹配,那么执行就会停止,并且在该过程中不会进行进一步的处理,但是内部请求无论如何都会被发送出来,所以第二次传递是通过相同的规则集进行的.仅当传递后URI未更改时,执行才会停止.

re:update 你的问题是,REQUEST_FILENAME环境变量实际上保存了一个路径(默认情况下是完整的文件系统路径,但是有一些曲折),所以%{DOCUMENT_ROOT}/files /%{REQUEST_FILENAME}最终变成了可怕的东西.

至于解决方案......我认为这很棘手.如果.htaccess是root用户,那就容易多了.我现在能想到的唯一解决方案是:

RewriteEngine on

RewriteCond %{REQUEST_URI} script/(.*)$
RewriteCond %{DOCUMENT_ROOT}/files/%1 -f
RewriteRule .* true.txt [L]

RewriteCond %{REQUEST_URI} !(true.txt)|(false.txt)
RewriteRule .* false.txt [L]
Run Code Online (Sandbox Code Playgroud)

它相当丑陋,而且不具备扩展性或便携性.在第一个条件下,我得到文件的名称,在第二个我检查它是否存在,如果它存在,它是真的.其他一切都是假的.然后,如果文件目录也在.htaccess的范围内,那么它的大小更容易和更好.