1

リダイレクトが(RewriteCondではなく)RewriteRuleに依存している理由がわかりません。

私の.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>

ルートフォルダには次のものが含まれます。

true.txt(「true」を含む)
false.txt(「false」を含む)
test.txt(「test」を含む)

私が開こうとするとtest.txt私は得ますtrue、そして私が開こうとするとnonexist.txt私も得trueます。

今、私は私の.htaccessを変更します:

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

そして今、私が開こうとするとtest.txt私は得ます、そして私が開こtestうとするとnonexist.txt私は得falseます。

更新:回答をありがとう、私はそれがどのように機能するかを理解しましたが、1つの問題がまだ存在します。別のディレクトリに「ファイルが存在するかどうか」を確認しようとすると、常に。が返されます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]

私はいつも得るfalse。私も試しRewriteCond ../files/%{REQUEST_FILENAME}てみましたが、常にfalse結果が出ています。

フォルダに移動test.txtして変更すると、すべて正常に機能します。scriptRewriteCond %{REQUEST_FILENAME}

4

3 に答える 3

7

これは、mod_rewriteの動作方法によるものです。ユーザーがtest.txtをリクエストすると、mod_rewriteがリクエストをキャッチしてURIをfalse.txtに書き換え、次に、false.txtの内部リクエストを送信して、2回目のパスを作成します。これは、キャッチされて書き換えられます。 true.txtに。次に、3番目のパスが作成され、リクエストがキャッチされてtrue.txtに書き換えられますが、URIは同じままであるため、これ以上パスは作成されません。

直感に反しますが、それには論理があります。ドキュメントの制御フロー図は次のとおりです。

mod_rewriteの制御フロー図

[L]フラグは、再帰を停止するための魔法の弾丸としてアドバタイズされることがよくありますが、実際には、リクエストがパターンに一致すると実行が停止し、そのパスでそれ以上の処理が行われないようにしますが、内部リクエストはとにかく送信されるので、2番目のパスは同じルールセットを介して行われます。パス後にURIが変更されていない場合にのみ、実行が停止します。

re:update 問題は、REQUEST_FILENAME環境変数が実際にパスを保持していることです(デフォルトでは完全なファイルシステムパスですが、それにはいくつかの工夫があります)。したがって、%{DOCUMENT_ROOT} / files /%{REQUEST_FILENAME}はひどいものになってしまいます。 。

解決策については...まあ、それはトリッキーだと思います。.htaccessがルートにあると、はるかに簡単になります。私が今考えることができる唯一の解決策は次のとおりです。

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]

それはかなり醜く、あまりスケーラブルでもポータブルでもありません。最初の条件でファイルの名前を取得し、2番目の条件でファイルが存在するかどうかを確認します。存在する場合はtrueです。他のすべては誤りです。繰り返しになりますが、ファイルディレクトリも.htaccessの範囲内にある場合は、規模が大きくて簡単です。

于 2012-07-04T10:40:29.663 に答える
1
RewriteEngine on

RewriteCond %{REQUEST_FILENAME} -f
RewriteCond %{REQUEST_URI} !(true|false)\.txt$
RewriteRule .* true.txt [L]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule .* false.txt [L]

RewriteCondtrue.txtファイルとfalse.txtファイルの書き換えを防ぐための2番目のファイルに注意し、Lルールの実行を停止するためのルールのフラグを立てます。これらはルールのループを防ぐためです。

更新

%{REQUEST_FILENAME}はフルパスであるため、パスに追加するとfalseになります(基本的に、これに一致しようとします。/var/www/subfolder/var/www/filename.txt

別のフォルダ内のファイルを照合するには、一致とURIの部分が必要になります...

これがあなたがそれをすることができる方法です:

RewriteEngine on
RewriteBase /

RewriteCond %{REQUEST_URI} ^/([^/]+)$
RewriteCond %{DOCUMENT_ROOT}/files/%1 -f
RewriteRule .* files/$0 [L]
  • 最初の条件は、要求がルートディレクトリ内のファイル名に対するものであるかどうかをチェックします(uriが/で始まることをチェックしますが、それ以上のスラッシュは含まれていません)
  • 最初の条件は、最初のスラッシュ以外のすべてを括弧で囲んでいることに注意してください。この一致したサブパターンは後で使用されます。
  • 2番目の条件は、サブパターンで保存された名前%1(最初の条件と一致)がfiles/内部のサブフォルダーに存在することを確認します。%{DOCUMENT_ROOT}
  • 両方のルールが一致した場合、リクエストはそのファイルに書き換えられます(サブリクエストを介して-ブラウザはリダイレクトされません)。
于 2012-07-04T10:20:21.913 に答える
0

「RewriteCond%{REQUEST_FILENAME}!-f」を使用する代わりに、
「RewriteCond%{THE_REQUEST}!-U」を試すことができます。これにより、アドレスが存在するかどうかがチェックされます。
ファイルパスとファイルが提供されるアドレスが異なる場合があり、前者は使用できなくなります。

例:

RewriteEngine On
RewriteCond %{THE_REQUEST} !-U
RewriteRule ^(.*/media/.*)\.(gif|png|jpe?g)$ https://xyz.company.com$1.$2 [NC,L,R=301]
于 2013-09-20T13:04:12.277 に答える