「^ //(。*)」(二重スラッシュで始まる)のRewriteRuleが単一のスラッシュにリダイレクトされないのはなぜですか?

Aug 17 2020

この書き換えルールをvHostコンテキストで使用します。ただし、//.*(ダブルスラッシュ)で始まる要求は書き換えられません。/.*へのリダイレクトで応答する代わりに、(シングルスラッシュ)からそれらを提供するだけです/.*

RewriteRule "^//(.*)" "/$1" [R=301,L]

なぜこれが機能しないのですか?

回答

2 MrWhite Aug 18 2020 at 06:51
RewriteRule "^//(.*)" "/$1" [R=301,L]

RewriteRule パターンが一致するURLパスでは、複数のスラッシュのすべてのインスタンスがすでに1つのスラッシュに削減されているため、これは一致しません。

このようなリクエストをリダイレクトするには、この「機能」を利用して「それ自体に」リダイレクトし、THE_REQUEST代わりにサーバー変数をチェックして、最初のリクエストに複数のスラッシュが存在するかどうかを判断します。THE_REQUESTはリクエストヘッダーの最初の行であり、クライアントから送信された未処理のリクエストURL(プロトコルとホスト名を除くがクエリ文字列を含む)を含みます。

たとえば、複数のスラッシュのすべてのインスタンスを、開始時だけでなく、URLパス全体で単一のスラッシュにリダイレクトするには、次のようにします。

RewriteCond %{THE_REQUEST} \s[^?]*//
RewriteRule (.*) $1 [R=301,L]

正規表現\s[^?]*//により、URLのクエリ文字列部分で複数のスラッシュが一致しないことが保証されます(そうしないと、リダイレクトループが発生します)。


RewriteCond %{THE_REQUEST} ^//二重スラッシュの他のすべてのインスタンスを無視して、二重スラッシュで始まるものにのみ書き換えルールを適用できるでしょうか?

完全ではありませんが、THE_REQUESTサーバー変数には実際にはHTTPリクエストヘッダーの最初の行全体が含まれています。言い換えると、次の形式の文字列です。

GET /foo/bar.html HTTP/1.1

またはGET //foo/bar.html HTTP/1.1、URLパスの先頭に二重スラッシュがある場合は、代わりに次のようなものが必要になります。

RewriteCond %{THE_REQUEST} \s//[^/]
RewriteRule (.*) $1 [R=301,L]

...すべてのリクエストメソッドをキャッチするため。具体的には、URLパスの先頭のみで、トリプルスラッシュなどではなく、ダブルスラッシュのみです。

\s//[^/]-これはスペースrequestメソッドの後)の後に2つのスラッシュとスラッシュ以外のもの(つまり、ドキュメントルート用のスペースまたはその他のURLパス)が続きます。