やりたいこと
/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]
おわり。