1

次のように、SEO に適した URL に書き換える必要があるすべてのクエリ文字列があります。

RewriteRule ^item_([0-9]+)/$ database.php?type=product&id=$1 [L]
RewriteRule ^post_([0-9]+)/$ articles.php?id=$1 [L]
... and so on

しかし、SEO とセキュリティの両方の理由から、item_123/?foo=barまたはdatabase.php?foo=barまたはpost_123/?type=product&id=321などの他のクエリ文字列を削除したいと考えています。

明らかに明らかな配置の解決策

RewriteCond %{QUERY_STRING} (.+)
RewriteRule (.*) http://www.example.com/$1? [R=301,L]

.htaccess の最後で、以前に Bean が処理されず、[L] タグで停止されたすべてのものを処理するために、実際には元の RewriteRule が壊れ、item_123/がパラメーターなしの空のdatabase.phpにリダイレクトされます。

%{REQUEST_URI} と %{QUERY_STRING} のすべてのペアの例外を明示的に書き留めることなく、以前に mod_rewrite されたものを除くすべてのクエリ文字列を削除することは可能ですか?

編集:

ソリューション A

# You do not need this whole block if you're running Apache v2.3.9+
RequestHeader set SOME-FANCY-NAME-FOR-THE-HEADER-AS-DESCRIBED-IN-THE-ABOVE-LINK 1 env=END

RewriteCond %{HTTP:SOME-FANCY-NAME-FOR-THE-HEADER-AS-DESCRIBED-IN-THE-ABOVE-LINK} =1 [NV]
RewriteRule .* - [L]

この[END]フラグは Apache v2.3.9+ でのみ機能するため、この動作をエミュレートする回避策を使用しました。

# Replace [L,E=END:1] with [END] if running Apache v2.3.9+
RewriteCond %{THE_REQUEST} ^GET\ [^?]+$
RewriteRule ^item_([0-9]+)/$ database.php?type=product&id=$1 [L,E=END:1]

?最初に THE_REQUEST のいずれかを制限するだけでは、item_123/?foo=barパターンの重複ページが見つかりません (404)。この[L,E=END:1]フラグは、mod_rewrite に現在の反復を停止して反復するように指示します。次の反復がトリガーRewriteRule .* - [L]され、その後の潜在的なループに到達するのをブロックします。フラグがサポートされていれば、[END]すぐに停止します。

RewriteCond %{QUERY_STRING} type=product
RewriteCond %{QUERY_STRING} id=([0-9]+)
RewriteRule ^database\.php$ http://www.example.com/item_%1/? [R=301,L]

これにより、クエリ内の意味不明なパラメータに関係なく、侵害された可能性のあるパターンの重複ページがdatabase.php?type=product&foo=bar&id=123正しい URL にリダイレクト (301) されます。正しい URL に到達すると、ループやエラー 500 を発生させることなくそこで停止します。

# If page is accessible without parameters

RewriteCond %{THE_REQUEST} ^GET\ [^?]+$
RewriteRule ^catalog/$ database.php [L,E=END:1]

RewriteCond %{THE_REQUEST} ^GET\ [^?]+\?
RewriteRule ^database\.php$ http://www.example.com/catalog/? [R=301,L]

?typeページがおよび&type上記のようなパラメーターなしでアクセス可能であるが、database.php?foo=barまたはとしてアクセスされる場合、クエリ文字列なしdatabase.php?で にリダイレクト (301) されます。catalog/ここでも、パターンのページはcatalog/?foo=bar見つかりません (404)。

# If page is not accessible without parameters

RewriteCond %{THE_REQUEST} ^GET\ [^?]+\?
RewriteRule ^database(\.php|/)?$ database.php [L,E=END:1]

パラメーターなしでページにアクセスできない場合は、書き換えを強制的に停止し (たとえば、にanyotherfile.php書き換えた場合に後で不要なリダイレクトを回避するためanyotherfile/)、有効なパラメーターが渡されていないことを認識したら、ページ自体に 404 ヘッダーを送信させることができます。

ソリューション A+B

承認されたソリューションのコードはそれ自体で正しいものですが、私のバージョンでは、他の多くの不正なパターンに一致するように書き換えを拡張しています。

上記のすべてのコードの後に​​受け入れられたソリューションからコードを追加すると、(以前は)item_123/?foo=barとパターンの見つからなかったリンクがキャプチャされ、クエリ文字列なしで正しい URLにcatalog/?foo=barリダイレクト (301) されます。ユーザーは、RSS アグリゲーターなどによって変更されたリンクをたどっても、目的の場所にたどり着くことができるため、これは理にかなっています。上記のコードの代わりにusing を使用するように変更すると、末尾の疑問符も削除されます.item_123/catalog/%{QUERY_STRING} (.+)%{THE_REQUEST} ^GET\ [.?]+\?%{THE_REQUEST} ^GET\ [^?]+$%{QUERY_STRING} ^$item_123/?

RewriteCond %{THE_REQUEST} ^GET\ [^?]+\?
RewriteRule (.*) http://www.example.com/$1? [R=301,L]
4

3 に答える 3

2

L フラグは止まりません。URLを変更した場合(変更した場合)、再注入します。したがって、実行した内部リダイレクト (書き換え) ごとに、最後の条件が OK であり、最後の書き換えがトリガーされます。

RewriteCond %{QUERY_STRING} (.+)
RewriteRule (.*) http://www.example.com/$1? [R=301,L]

これはクエリ文字列を切り取っているため (フラグ?なしQSAで終了)、パラメータなしの php スクリプトで終了します。

rewrite #1/1: item_5/ -> database.php?type=product&id=5
              L triggered, because URL changed, re-inject:
rewrite #1/2: database.php?type=product&id=5 -> http://www.example.com/database.php?
              R triggered, exiting

rewrite #2/1: http://www.example.com/database.php? -
              no rule matches, use as-is

代わりに、.php ファイルをリダイレクトしないように条件を最後に配置する必要があります。

RewriteCond %{QUERY_STRING} (.+)
RewriteCond %{REQUEST_URI} !^/[a-z]+\.php$    
RewriteRule (.*) http://www.example.com/$1? [R=301,L]

または、より最新の apache サーバー バージョンを使用している場合は、次のENDフラグを使用します。

RewriteRule ^item_([0-9]+)/$ database.php?type=product&id=$1 [END]
RewriteRule ^post_([0-9]+)/$ articles.php?id=$1 [END]
... and so on
于 2013-08-29T20:42:11.803 に答える
0

これを回避するには、次を使用します。

RewriteRule ^item_([0-9]+)/.*$ abc.php?type=product&id=$1 [L]

スラッシュの後に何にでも一致するように追加.*しましたが、それでもリダイレクトの有効なパターンです。

于 2013-08-29T20:41:33.867 に答える
0

これが役立つかどうかはわかりませんが、存在しないファイルを特定のphpファイル(rewrite.php)に送信することを処理する方法です

RewriteCond %{SCRIPT_FILENAME} !-d
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteRule ^.*$ ./rewrite.php

これにより、遭遇したほとんどすべてのケースを簡単に処理できます

于 2013-08-29T20:38:47.943 に答える