localでRails APIとWebクライアントを別途立てていた時に、クロスドメインとpre-flightへの対応が必要になりました。
Rails APIサーバ: localhost:3000
Webフロントエンド: localhost:3355
Webフロントエンドでは、HTTPクライアントとしてaxiosを利用しました。
クロスドメイン対応
クロスドメイン対応が無い場合、リクエストで"No 'Access-Control-Allow-Origin' header is present on the requested resource." とエラーが出ます
。
localhost:3355からのアクセスに対して、クロスドメイン対応をいれます。
config.action_dispatch.default_headers = {
'Access-Control-Allow-Credentials' => 'true',
'Access-Control-Allow-Origin' => 'http://localhost:3355',
'Access-Control-Request-Method' => '*'
}
未検証ですが、下記gemではrackレベルで対応可能のようです。
cyu/rack-cors
参考
Rails4アプリに対してクロスドメインでAjaxでCookieを送信したい場合
pre-flight対応
axiosは異なるオリジンに対してリクエストする時に、OPTIONSメソッドでpre-flightのリクエストを送信します。
How to disable OPTIONS request?
OPTIONSメソッドでリクエストしようとして404になります
Railsサーバは以下のようなエラーが出ます
Started OPTIONS "/user_token" for ::1 at 2017-03-06 17:57:46 +0900
ActiveRecord::SchemaMigration Load (3.9ms) SELECT `schema_migrations`.* FROM `schema_migrations`
ActionController::RoutingError (No route matches [OPTIONS] "/user_token"):
Railsでのpreflightリクエストの実装およびテスト例の実装を参考に実装してみます。
routes.rbの先頭でOPTIONSメソッドでのリクエストに対して、options_requests_controllerをルーティングします。
Rails.application.routes.draw do
match '*path' => 'options_request#preflight', via: :options
# other resources
end
ヘッダに'Access-Control-Max-Age', 'Access-Control-Allow-Headers', 'Access-Control-Allow-Methods' をつけて返します。
class OptionsRequestController < ApplicationController
ACCESS_CONTROL_ALLOW_METHODS = %w(GET OPTIONS).freeze
ACCESS_CONTROL_ALLOW_HEADERS = %w(Accept Origin Content-Type Authorization).freeze
def preflight
set_preflight_headers!
head :ok
end
private
def set_preflight_headers!
response.headers['Access-Control-Max-Age'] = ACCESS_CONTROL_MAX_AGE
response.headers['Access-Control-Allow-Headers'] = ACCESS_CONTROL_ALLOW_HEADERS.join(',')
response.headers['Access-Control-Allow-Methods'] = ACCESS_CONTROL_ALLOW_METHODS.join(',')
end
end