Railsでは、request.subdomain
で簡単にサブドメインの判別ができます。
詳しくはRailsCastsに書いてありますが、特にgemを入れなくても、url_forに1つ機能追加するだけで、実用的なサブドメイン機能が使えます。
何が嬉しいかというと、
- ja.example.com
- en.example.com
のようなwikipedia風のURLを作ったり、ブログサイトでユーザ毎にサブドメインを切ってあげたりできるわけですね。
サブドメインは当然HTTPリクエスト時のホスト名から取得されるので、環境によってはうまく取得できない場合があります。
ローカルでテストする場合
通常localhost:3000で開発すると思いますが、これにサブドメインを付けてja.localhost:3000としても、127.0.0.1に名前解決はしてくれません。
hostsファイル(/etc/hosts)はワイルドカードが使えないので、個別に記述する必要があります。
RailsCastsにあるように、「lvh.me」というドメインが127.0.0.1を向いているので、ja.lvh.me:3000とやるのがお手軽です。
nginxをリバースプロキシにする場合
リバースプロキシからは、X-Forwarded-Hostを送ってやる必要があります。
Railsのドメイン判別は以下のようになっているので、X-Forwarded-Hostがあると、HTTP_HOSTに優先して採用されます。
# actionpack-3.2.8/lib/action_dispatch/http/url.rb # Returns the \host for this request, such as "example.com". def raw_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
nginxのconfファイルとしてはこんな感じになりますね。
proxy_redirect off; proxy_set_header X-Forwarded-Proto http; proxy_set_header X-Forwarded-Host $host; # これ! proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $remote_addr; proxy_pass http://myproxy
nginxで多段リバースプロキシする場合
多段Revese Proxyしたいときもあると思います。
たとえば、社内サーバでIP節約のためにReverse Proxyを通す必要があり、かつRailsアプリサーバはproductionで動かしたいので、assetsファイルをserveするためにアプリサーバ内でnginxを動かしたい場合です。
多段の場合、外側のnginxは上記設定のままでOKですが、内側のnginxは一部パラメータを改めて渡す設定が必要になったりします。
X-Forwarded-Hostは設定不要でしたが、手元の環境では、x_forwarded_forとx_forwarded_protoを改めて渡さないと、force_sslでリダイレクトループが発生しました。
proxy_redirect off; proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto; proxy_set_header Host mangareborn-stg.bpsinc.jp; proxy_set_header X-Real-IP $http_x_real_ip; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://myproxy
nginxでパラメータをデバッグする
上記のような設定をしていると、思うようにヘッダが渡らないことも多いと思います。
nginxでどの変数が使えてどんな値が入っているかを知りたいときは、アクセスログに出すのが手っ取り早いです。
log_format custom 'MY HEADER $host $proxy_add_x_forwarded_for'; # 好きにいじる access_log /var/log/nginx/mycustom.log custom;
本記事の対象バージョンはRails 3.2.8です