Edited at

RewriteRuleでURLエンコードされたクエリ付きURLへリダイレクトするには

More than 1 year has passed since last update.


やりたいこと


/foo をリクエストされたら http://example.com/?q=%26 へリダイレクトしたい。


%26& をURLエンコードしたものなので、 q の値として & という1文字を渡すというだけのURLです。


%1, %2, … が後方参照用の変数と解釈される罠

まず最初は単純に以下のような RewriteRule を書くと思う。

RewriteRule ^/foo http://example.com/?q=%26 [R,L]

これは期待通りに動いてくれない。

実際に /foo にアクセスしてみると http://example.com/?q=6 というURLに飛ばされます。

何故か? RewriteRule では直前の RewriteCond で正規表現を利用した際にマッチしたグループを %1, %2, %3... という形で後方参照できるという機能がある為です。

つまり %2 の部分が後方参照用の変数と解釈されて、しかし直前で RewriteCond は使っていないので %2 は空となっており、結果として %26 の部分が (空文字) + 6 つまり 6 になってしまったわけです。

後方参照用の変数と解釈されないためには % を全て \% に書きなおしてやれば、そのまま % という1文字として解釈してくれることになっています。


勝手にURLエンコードされる罠

後方参照の罠を抜けるために以下のように書き直しました。

RewriteRule ^/foo http://example.com/?q=\%26 [R,L]

しかしこれも期待通りに動いてくれません。

実際に /foo にアクセスしてみると http://example.com/?q=%2526 というURLに飛ばされます。

何故か? RewriteRule ではリダイレクト先URLにクエリが付いていてかつその値にURLエンコードすべき文字が含まれていると勝手にURLエンコードしてくれるという(邪魔な)機能がある為です。

つまり % の部分がURLエンコードされた結果 %25 に置換され、結果として %26%2526 になってしまったわけです。

この勝手にURLエンコードされる仕様を回避するには NE または noescape というフラグを付けてやればよい事になっています。


完成形

これでようやく期待通りのリダイレクトが出来ました。

RewriteRule ^/foo http://example.com/?q=\%26 [R,L,NE]

おわり。