LoginSignup
1
0

More than 1 year has passed since last update.

CORSとは

CORSとはCross Origin Resource Sharingの略語で、日本語で表すとオリジン間リソース共有です。
ブラウザでは、セキュリティの観点から異なるオリジンを持つクライアント側からのHTTPリクエストを制限しています。
これを同一オリジンポリシーと言います。

例えば、http://localhost:3001でapiサーバーが立ち上がっており、http://localhost:3000でクライアント側のサーバーが立ち上がっている場合に、クライアント側からapi側にリクエストをすると、オリジンが異なるため以下のようなエラーが出力されます。

    Access to XMLHttpRequest at 'http://localhost:3001/api/v1/posts' from origin 'http://localhost:3000' has 
    been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

レスポンスヘッダーにAccess-Control-Allow-Originがないため、ブラウザでは制限されます。
異なるオリジンからのHTTPリクエストの可能にするには、バックエンド側での設定が必要です。

rack-cors

Railsでは、rack-corsを使うことによって、オリジン間リソース共有が可能になります。
なぜRackなのかというと、RailsがRackベースのアプリケーションであり、レスポンスを返す際にRackを噛ませているからです。
リクエストがあった場合、以下のような順番でWeb ServerからRails側までリクエストが送られます。

                    ********************
                           Rails
                    ********************
                    
                            ↑ ↓
                    
                    ********************
                           Rack
                    ********************
                    
                            ↑ ↓
                    
                    ********************
                         Web Server
                    ********************

rack-corsを導入すると、Rackからのレスポンスのレスポンスヘッダーの設定を変更することができます。

どのように変化するのか、Rackミドルウェアを作成してRackからのレスポンスの中身を確認してみます。
↓ Rack Middlewareについてはこちら

今回はプロジェクトディレクトリ直下にミドルウェア用のファイルを作成します。

sample_middleware.rb
    class SampleMiddleware
        def initialize(app)
            @app = app
        end
    
        def call(env)
            status, headers, body = @app.call(env)
            puts "-" * 15 + " " + "status" + " " + "-" * 15
            puts status
            puts ""
            puts "-" * 15 + " " + "headers" + " " + "-" * 15
            puts headers
            return [status, headers, body]
        end
    end

@app.call(env)によってRails側にリクエストが送られ、それに対するレスポンスがstatus, request, bodyに入ります。
Rackの設定ファイルであるconfig.ruにミドルウェアを含めるようにします。

config.ru
    # This file is used by Rack-based servers to start the application.
    
    require_relative "config/environment"
    require_relative "sample_middleware" # <= 追加
    
    use SampleMiddleware # <= 追加
    
    run Rails.application
    Rails.application.load_server

以上のように設定して、api側にリクエストしてみると以下のような結果を得られます。

    --------------- status ---------------
    200
    
    --------------- headers ---------------
    {"X-Frame-Options"=>"SAMEORIGIN", "X-XSS-Protection"=>"0", "X-Content-Type-Options"=>"nosniff", 
    "X-Download-Options"=>"noopen", "X-Permitted-Cross-Domain-Policies"=>"none", "Referrer-Policy"=>"strict-origin-when-cross-origin", 
    "Content-Type"=>"application/json; charset=utf-8", "ETag"=>"W/\"04feffc04d2090381867383349de9809\"", 
    "Cache-Control"=>"max-age=0, private, must-revalidate", "X-Request-Id"=>"ecf605ef-ec11-4f73-afa1-49ad20be3820", "X-Runtime"=>"0.045787", 
    "Server-Timing"=>"start_processing.action_controller;dur=3.481201171875, sql.active_record;dur=11.874755859375, instantiation.active_record;dur=0.32275390625, process_action.action_controller;dur=20.947021484375", "Vary"=>"Origin"}

statusコード200ですが、レスポンスヘッダーに'Access-Control-Allow-Origin'がないため、ブラウザでは制限されます。

rack-corsをインストールして、config/initializers/cors.rbを以下のように設定します。

cors.rb
    # Be sure to restart your server when you modify this file.
    
    # Avoid CORS issues when API is called from the frontend app.
    # Handle Cross-Origin Resource Sharing (CORS) in order to accept cross-origin AJAX requests.
    
    # Read more: https://github.com/cyu/rack-cors
    
    Rails.application.config.middleware.insert_before 0, Rack::Cors do
      allow do
        origins "*"
    
        resource "*",
          headers: :any,
          methods: [:get, :post, :put, :patch, :delete, :options, :head]
      end
    end

リクエストを送ると以下のような結果が得られます。

    --------------- status ---------------
    200
    --------------- headers ---------------
    {"Access-Control-Allow-Origin"=>"*", "Access-Control-Allow-Methods"=>"GET, POST, PUT, PATCH, DELETE, OPTIONS, HEAD", 
    "Access-Control-Expose-Headers"=>"", "Access-Control-Max-Age"=>"7200", "X-Frame-Options"=>"SAMEORIGIN", 
    "X-XSS-Protection"=>"0", "X-Content-Type-Options"=>"nosniff", "X-Download-Options"=>"noopen", "X-Permitted-Cross-Domain-Policies"=>"none",
    "Referrer-Policy"=>"strict-origin-when-cross-origin", "ETag"=>"W/\"04feffc04d2090381867383349de9809\"", "Cache-Control"=>"max-age=0, private, must-revalidate",
    "X-Request-Id"=>"e8085ff2-8ba0-4433-8548-41f1d525afc8", "X-Runtime"=>"0.056507", "Server-Timing"=>"start_processing.action_controller;dur=3.614501953125, sql.active_record;dur=8.42626953125, instantiation.active_record;dur=0.226806640625, process_action.action_controller;dur=16.123779296875", "Vary"=>"Origin"}

Access-Control-Allow-Origin, Access-Control-Allow-Methods, Access-Control-Expose-Headersの3つが新しく追加されています。
"Access-Control-Allow-Origin"=>"*"は、どのオリジンからのリクエストも許可することを意味しているためブラウザで制限されることはなく正常に動作します。

rack-corsを導入するとcors.rbの設定に基づいて、レスポンスヘッダーが変更されることがわかります。

参考にしたサイト

1
0
0

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
1
0