LoginSignup
87
71

More than 5 years have passed since last update.

Rails APIでクロスドメインとpre-flight対応

Last updated at Posted at 2017-03-06

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." とエラーが出ます

スクリーンショット 2017-03-06 17.46.37.png

localhost:3355からのアクセスに対して、クロスドメイン対応をいれます。

config/application.rb
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になります
スクリーンショット 2017-03-06 17.57.59.png

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をルーティングします。

config/routes.rb
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' をつけて返します。

app/controllers/options_request_controller.rb
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
87
71
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
87
71