client ---> proxy1 ---> proxy2 ---> rails app
※ proxy1/2はX-Forwarded-Host設定
上記のような環境ではrailsにX-Forwarded-Hostで"proxy1, proxy2"なリクエストが届く。
railsでrequest.hostするとproxy2のホスト名が返される。
1.6.0.alphaの該当ソースでは以下のようになっていてX-Forwarded-Hostの最後をとってくるようになっている。
なぜ最後を返してくるのか、最初では駄目なのかを調べてみた。
def host
# Remove port number.
host_with_port.to_s.sub(/:\d+\z/, '')
end
def host_with_port
if forwarded = @env["HTTP_X_FORWARDED_HOST"]
forwarded.split(/,\s?/).last
else
@env['HTTP_HOST'] || "#{@env['SERVER_NAME'] || @env['SERVER_ADDR']}:#{@env['SERVER_PORT']}"
end
end
調べた結果
同じような質問があったので追ってみると該当箇所の修正を行ったチケットを見つけた。
- 変更のチケット(Archiveサイトより):#3397 ([PATCH] CgiRequest returns incorrect host name in event of multiple proxies) - Rails Trac - Trac
- チェンジセット(Archiveサイトより):Changeset 3412 - Rails Trac - Trac
チケットの内容としてはActionController::Base::redirect_toでX-Forwarded-Hostが複数あるとうまくいかないのを最後のを取得することで対応したというものみたい。
最初のではなく最後のを取るようにしたのはリダイレクトする先は最後のプロキシのホストが適切だと判断したためのよう。
納得したけどclientがリクエストしてきたホストを取りたい場合にはRack::Request#hostは使えないということかな、、、