web-dev-qa-db-ja.com

RewriteRuleの場所に応じて、末尾に二重のスラッシュが表示されるのはなぜですか?

次のコードを使用して、すべてのwwwリクエストをwww以外のURLに送信しています。

RewriteEngine On
RewriteCond %{HTTP_Host} ^www\.example\.org$ [NC]
RewriteRule ^(.*)$ http://example.com/$1 [R=301,L]

これは、私のWebサイトのルートにある.htaccessファイル内でうまく機能します。
例えば、
www.example.com-> example.com/
www.example.com /-> example.com/
www.example.com/other_page-> example.com/other_page

ただし、これと同じコードをVirtualHost構成に移動すると、書き換えられたURLには末尾に二重のスラッシュが含まれます。
www.example.com-> example.com//
www.example.com /-> example.com//
www.example.com/other_page-> example.com//other_page

書き換えルールからスラッシュを削除して修正しました。

RewriteEngine On
RewriteCond %{HTTP_Host} ^www\.example\.org$ [NC]
RewriteRule ^(.*)$ http://example.com$1 [R=301,L]

しかし、その理由がわかりません。誰もが理由を知っていますか?

9
davekaro

私が理解しているように、.htaccessファイルでは、mod_rewriteがルールで処理する文字列は、.htaccessファイルが存在するディレクトリを基準にしているため、先頭に/がありません。

VirtualHostエントリでは、処理する文字列はサーバーのルートに対して絶対的であるため、/が含まれます。

Mod_rewriteの動作に微妙な違いがあります。

同様の問題と解決策を持っている人がいます:

http://forum.modrewrite.com/viewtopic.php?p=56322&sid=77f72967f59200b5b5de174440234c3a

これは、エスケープを正しく覚えていると仮定すると、どちらの場合でも機能するはずです。

RewriteEngine On
RewriteCond %{HTTP_Host} ^www\.example\.org$ [NC]
RewriteRule ^\/?(.*?)$ http://example.com/$1 [R=301,L]
10
Neobyte

これは、(.*)で最初のスラッシュをキャプチャし、その前に新しい場所/$1で別のスラッシュを適用しているために発生しています。サーバーごとのコンテキストではなく、ディレクトリごとのコンテキストで操作する場合、mod_rewriteの動作が少し異なるため、これは以前には起こりませんでした。

オプションでスラッシュを横取りすることで、これを回避できます。さらに、余剰ドメインを持つ空のVirtualHostでRedirectMatchを使用できます。これにより、処理が少し少なくなり、見た目がきれいになります。

<VirtualHost *>
ServerName example.com
ServerAlias other.example.com
..
RedirectMatch permanent ^/?(.*) http://example.com/$1
</VirtualHost>

2
Dan Carley

完全を期すために、この投稿を含めています。

Apacheのドキュメント は、この動作が非常にうまく発生する理由を説明し、「RewriteBase」ディレクティブが存在する理由です。

.htaccessファイルに「RewriteBase」ディレクティブを含めるだけで、目的の結果が得られます。

例:

RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_Host} ^www\.example\.org$ [NC]
RewriteRule ^(.*)$ http://example.com/$1 [R=301,L]

Apache 2.2 mod_rewriteドキュメントから:

RewriteBaseディレクティブは、ディレクトリごとの書き換えのベースURLを明示的に設定します。

私の経験則では、ほとんどの場合、.htaccessファイルでは「RewriteBase」を使用し、Apache構成では使用しないことです。

1
Andrew

この問題を処理する時間がなかったので、//を/に書き直してください:)

RewriteCond %{THE_REQUEST} //
RewriteRule ^(.*)$ http://domain.com [R=301,L]
0
user956584