目次
Rails上でHTTPヘッダを取得する方法
RailsアプリケーションでHTTPヘッダの情報を取得する場合はrequest.headersあるいはrequest.envを利用します。
### コンソール
$ curl http://localhost:3001/health
### Rails側
From: /app/app/controllers/health_controller.rb:3 HealthController#show:
2: def show
=> 3: binding.pry
4: render json: { message: 'ok' }, status: :ok
5: end
# フィールド名が『HTTP_HOST』 の値を取得
## request.headersを利用した場合
[1] pry(<HealthController>)> request.headers["HTTP_HOST"]
=> "localhost:3001"
## request.envを利用した場合
[2] pry(<HealthController>)> request.env["HTTP_HOST"]
=> "localhost:3001"
# 接頭辞が『HTTP_』のHTTPヘッダの一覧取得
## request.headersを利用した場合
[3] pry(<HealthController>)> request.headers.filter_map { |key, value| "#{key}: #{value}" if key.start_with?("HTTP_") }
=> ["HTTP_VERSION: HTTP/1.1", "HTTP_HOST: localhost:3001", "HTTP_USER_AGENT: curl/7.85.0", "HTTP_ACCEPT: */*"]
## request.envを利用した場合
[4] pry(<HealthController>)> request.env.filter_map { |key, value| "#{key}: #{value}" if key.start_with?("HTTP_") }
=> ["HTTP_VERSION: HTTP/1.1", "HTTP_HOST: localhost:3001", "HTTP_USER_AGENT: curl/7.85.0", "HTTP_ACCEPT: */*"]
HTTPヘッダをRailsに渡す際の仕様について
RailsアプリケーションはRack(RubyでWebサーバを立ち上げるためのインタフェース)を利用してデータのやりとりを行っています。
Rackの仕様はRFC 3875 – The Common Gateway Interface (CGI) Version 1.1に準拠しており、4.1.18. Protocol-Specific Meta-Variablesの項目には以下のような記述があります。
- HTTPヘッダのフィールド名を大文字に変換する
- 『-』を『_』に置き換える
- 『HTTP_』を先頭に付ける
つまり、リクエスト時に送信されたHTTPヘッダのフィールド名はRailsアプリケーションに届く過程で暗黙的に変換されます。
ですので、Railsアプリケーション上でHTTPヘッダから値を取得する際は、リクエスト時のフィールド名と異なっているので注意が必要です。
### コンソール
$ curl http://localhost:3001/health -H 'X-CUSTOM-TOKEN: foo'
### Rails側
From: /app/app/controllers/health_controller.rb:3 HealthController#show:
2: def show
=> 3: binding.pry
4: render json: { message: 'ok' }, status: :ok
5: end
# request.headersを利用した場合
[1] pry(<HealthController>)> request.headers["HTTP_X_CUSTOM_TOKEN"]
=> "foo"
# request.envを利用した場合
[2] pry(<HealthController>)> request.env["HTTP_X_CUSTOM_TOKEN"]
=> "foo"
# request.headersを利用した場合、リクエスト時のヘッダ名でも取得できる
[3] pry(<HealthController>)> request.headers["X-CUSTOM-TOKEN"]
=> "foo"
# request.envを利用した場合、リクエスト時のヘッダ名では取得できない
[4] pry(<HealthController>)> request.env["X-CUSTOM-TOKEN"]
=> nil
HTTPヘッダに独自のフィールドを追加する場合、名前にはアンダースコアではなくハイフンを使った方が良い
nginxのunderscores_in_headers
(アンダースコアを含んだHTTPフィールドの有効可否の設定)の設定がデフォルトでOFFになっていることからもわかる通り1、原則HTTPヘッダのフィールド名にアンダースコアは含めないほうがよいです。
ですので、HTTPヘッダに独自のフィールドを追加する際は名前にはアンダースコアではなくハイフンを利用するようにしましょう。
Rails上でHTTPヘッダが取得できない場合はフィールド名にアンダースコアが含まれているか確認する
たとえば、Railsアプリケーションの前段にunderscores_in_headers
がOFFのnginxが配置されいている場合、アンダースコアが含まれたフィールド名のHTTPヘッダはRailsアプリケーションに届きません。
もしHTTPヘッダの情報がRailsアプリケーションに届かない場合はヘッダ名を確認するとよいです。
さいごに
Twitter(@nishina555)やってます。フォローしてもらえるとうれしいです!