AWSを使っていて
- ELBでSSL Terminationを行い、APPサーバはHTTPアクセスのみ
- サイトは基本SSLで、HTTPアクセスはforce_sslでHTTPSにリダイレクト
- ELBのヘルスチェックではRailsの稼働まで確認したい
という時に、ELBのヘルスチェックまでforce_sslでHTTPSにリダイレクトされると困る。
Rails3の時はssl_optionsのexcludeで対応してたんですが、
config/environments/production.rb
config.force_ssl = true
config.ssl_options = { exclude: proc { |env| !env['HTTP_X_FORWARDED_FOR'] } }
Rails4だとこのオプションが効かなくなっていたので、対応方法をメモ。
基本的にはconfigではなく、controllerのforce_sslメソッドを使ってifオプションでELBからのヘルスチェックを除外する。
その1. HTTP_X_FORWARDED_FORを見る
ELB経由のアクセスの場合はHTTP_X_FORWARDED_FORヘッダが付与されるので、それがない場合はELBからのヘルスチェックだと見なす
app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
force_ssl if: :use_ssl?
def use_ssl?
Rails.env.production? && request.env['HTTP_X_FORWARDED_FOR'].present?
end
end
その2. ヘルスチェック用のコントローラを作る
ヘルスチェック用のコントローラを作り、そこだけHTTPでもアクセスできるようにする
app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
force_ssl if: :use_ssl?
def use_ssl?
Rails.env.production?
end
end
app/controllers/healthcheck_controller.rb
class HealthcheckController < ApplicationController
def index
render text: 'Healthy!'
end
def use_ssl?
false
end
end