Rails.application.configureで環境毎にcorsのallow_originsを設定する

こんにちは!kossyです!



さて、今回はRails.configurationに環境毎にoriginを定義して、
corsのoriginの設定を行う方法について、ブログに残してみたいと思います。




環境
Ruby 2.6.3
Rails 6.0.3
MacOS Mojave



corsとは?

みんな大好きMDNのcorsの解説を引用します。

Cross-Origin Resource Sharing (CORS) は、
追加の HTTP ヘッダーを使用して、あるオリジンで動作しているウェブアプリケーションに、
異なるオリジンにある選択されたリソースへのアクセス権を与えるようブラウザーに指示するための仕組みです。
ウェブアプリケーションは、自分とは異なるオリジン (ドメインプロトコル、ポート番号) にあるリソースをリクエストするとき、
オリジン間 HTTP リクエストを実行します。

オリジン間リクエストの一例: https://domain-a.com で提供されている
ウェブアプリケーションのフロントエンド JavaScript コードが
XMLHttpRequest を使用して https://domain-b.com/data.json へリクエストを行う場合。

セキュリティ上の理由から、ブラウザーは、スクリプトによって開始されるオリジン間 HTTP リクエストを制限しています。
例えば、 XMLHttpRequestや Fetch API は同一オリジンポリシーsame-origin policyに従います。
つまり、これらの API を使用するウェブアプリケーションは、
そのアプリケーションが読み込まれたのと同じオリジンに対してのみリソースのリクエストを行うことができ、
それ以外のオリジンの場合は正しい CORS ヘッダーを含んでいることが必要です。

出典: https://developer.mozilla.org/ja/docs/Web/HTTP/CORS

要はリクエスト元のオリジン(ドメイン + プロトコル + ポートを含めたもの)とリクエスト先のオリジンが異なる時に、
異なるオリジンにあるデータにアクセスしたいって時にブラウザに許可を与える仕組みです。

例えば、APIのエンドポイントURLとフロントエンドアプリのURLが異なっている場合、
corsへの対応が必要になります。

RailsAPIに徹して、Vue.jsやReactはRailsから受け取ったJSONを加工して表示するという構成のWebアプリがあれば、
cors対応を行うことになるかと思います。


Rails.application.configureでユーザー定義値を設定する

Railsで環境毎にグローバルにユーザー定義値を設定する場合、

config/environments/**.rb内で、

Rails.application.configure do
  # 省略

  config.define_user_value = 'value'

end

のように定義すると、

$ Rails.configuration.define_user_value
=> "value"

のようにどこからでも呼び出せるようになります。


この手法を応用して、corsのoriginsの値を定義していきます。

originsの設定

config/environments/**.rbに以下を定義します。

Rails.application.configure do
# 省略
  config.allow_origins = ['https://allow_origin_url.co.jp', 'https://second_allow_origins_url.com']
end

次にconfig/initializers/cors.rbを以下のように編集します。

Rails.application.config.middleware.use Rack::Cors do
  allow do
    origins Rails.configuration.allow_origins
    resource '*',
    :headers => :any,
    :expose  => ['access-token', 'expiry', 'token-type', 'uid', 'client'],
    :methods => [:get, :post, :options, :delete, :put]
  end
end

このように設定することで、環境毎に許可するoriginsを設定することができます。




勉強になりました。