web-dev-qa-db-ja.com

Apacheの書き換え条件が機能しないのはなぜですか?

.htaccessファイルにリダイレクト書き込みを実行しようとしました:

RewriteEngine on
RewriteRule article-1 www.another-site.com/article-1 [R=301,L,NC]

そしてそれは正しく動作します。とにかく、私が書き換え条件を追加すると、例えば:

RewriteEngine on
RewriteCond %{HTTP_REFERER} domain.tracker.com [NC]
RewriteRule article-1 www.another-site.com/article-1 [R=301,L,NC]

条件が常にfalseと評価されたかのように、リダイレクトが実行されなくなりました。リファラーは正しく評価されます(www.site.com?ref =%{HTTP_REFERER}にリダイレクトしようとしましたが、www.site.com?ref = https://domain.tracker.com/?queries = vals 、これは正しいリファラーです)。

私が.htaccessファイルに持っている他の唯一の書き換え命令は

#BEGIN WORDPRESS    
<IfModule mod_rewrite.c>
    RewriteRule ^index\.php$ - [L]
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule . /index.php [L]
    </IfModule>
#END WORDPRESS

なぜ条件が機能しないのですか? WordPress命令と競合する可能性がありますか?ホスティングプロバイダーに依存する可能性がありますか?

1
Arthu83

WordPressディレクティブは.htaccessファイルの下部にありますが、私は上部に配置しています。

それは正しいです。

RewriteCond %{HTTP_REFERER} domain.tracker.com [NC]

投稿したRewriteCondディレクティブには、これが機能しなくなるような実際の問題はありません。 条件は、HTTPRefererヘッダー文字列 "domain.tracker.com"(大文字と小文字を区別しない)が含まれている場合に成功します。それだけです、それ以上のことは何もありません。CondPatternは正規表現であるため、リテラルドットと一致させるには、ドット(.)をバックスラッシュでエスケープする必要があります。そうでない場合は、任意の文字(あなたの例の場合)。したがって、ディレクティブは一致しすぎる可能性がありますが、動作を停止することはありません。例えば。また、次の形式のHTTPリファラーとも一致します:http://example.com/domain-tracker-com/foo

このような状態が機能しない最も一般的な原因は、HTTP_REFERERに期待するものが含まれていない場合です。ご存じのとおり、Refererヘッダーは信頼性が低いことで有名です。クライアントやウェブサイトによってブロックされる可能性があり、簡単に偽造されます。あなたのテストは表示されますが期待通りに合格したRefererを示しているので、それは謎です。

RewriteRule article-1 www.another-site.com/article-1 [R=301,L,NC]

ただし、RewriteRule置換(つまり、www.another-site.com/article-1)はこのコンテキストでは無効であり、前述のようにリダイレクトされません。外部ホストへwww.another-site.com。必要なスキーム(例:http)が欠落しており、次の形式である必要があります:http://www.another-site.com/article-1。言い換えれば、絶対URL

SOに関する関連質問 で絶対URLを使用していたので、これは単にタイプミスであるかどうか疑問に思いましたが、コメントで、書かれているとおりに正しいことを確認したようです。)

RewriteRule置換がスキーム(httpまたはhttps)またはスラッシュ(/)で始まらない場合、相対 URLパスと見なされます。ディレクトリごとの.htaccessファイルでは、「ディレクトリプレフィックス」と呼ばれる.htaccessファイルを含むファイルシステムディレクトリに関連していると見なされることを意味します(RewriteBaseディレクティブに別段の記載がない限り、またはディレクティブは「継承」されています)。このディレクトリプレフィックスは、書き換えプロセスの最後に置換に追加されます。上記のRewriteRuleの場合、これにより、フォームのリダイレクトが完全に無効になる可能性があります。

http://example.com/home/user/public_html/www.another-site.com/article-1

ここで、/home/user/public_html/はディレクトリプレフィックスです。 .htaccessファイルの場所の絶対ファイルシステムパス。 example.comは現在のホストです(おそらくホスト要求されています)。 www.another-site.com/article-1は、RewriteRule置換に記載されている相対URLパスです。

上記のように、絶対URLを形成するには、スキーム/プロトコルを含める必要があります。

RewriteCond %{HTTP_REFERER} domain\.tracker\.com [NC]
RewriteRule article-1 http://www.another-site.com/article-1 [R=301,L,NC]

また、正規表現article-1は、要求されたURL内の任意の場所で文字列「article-1」と一致することに注意してください。例えば。 /foo-article-1-bar/も一致します。特定のURLに一致する場合は、その特定のURLに一致する必要があります。 ^article-1$。宛先サイトのURLパスが同じである場合は、URLパスをキャプチャし、RewriteRule置換で後方参照を使用することで繰り返しを回避できます。例えば:

RewriteRule ^(article-1)$ http://www.another-site.com/$1 [R=301,L,NC]

条件が機能しないのはなぜですか?

与えられた情報から、合理的な説明はありません。

WordPress命令との競合でしょうか?

これらのディレクティブを前に WordPressフロントコントローラーに配置することで、その可能性をほぼ排除できました。

それはホスティングプロバイダーに依存するでしょうか?

それはほとんどありません。


代わりに、単純なクエリ文字列でこれを試してください。

RewriteCond %{QUERY_STRING} ^bar=1$
RewriteRule ^(foo)$ http://example.com/$1 [R,QSD,L]

リクエスト:

/foo?bar=1

そして、一時的に(302)次の場所にリダイレクトする必要があります。

http://example.com/foo

すなわち。同じURLパスですが、クエリ文字列が削除されています。

1
MrWhite