Ruby on RailsでのCORS対策
はじめに
社内の開発では、全てRuby on Railsでの開発をしており、個人開発をする際はバックエンドをRailsにして何か作ろうと思ったのでその際の備忘録です。
今回は、Ruby on Railsをバックエンドに、Reactをフロントエンドに使ったプロジェクトで少し詰まったCORSについての話とRailsでどう実装するのか、またAxiosを使ったAPIリクエスト時に発生するネットワークエラーについて解決したいと思います。
1. CORSとは?
CORS(Cross-Origin Resource Sharing)は、異なるオリジン間でリソースを共有するための仕組みです。
通常、ブラウザはセキュリティ上、異なるオリジン間のリクエストをブロックしますが、CORSヘッダーを正しく設定することで特定のオリジンからのアクセスを許可することができます。
今回であるとバックエンドはlocalhost://3000であり、フロントエンドはlocalhost://3001になるので、フロントエンドからデータを送った場合(リクエスト)にバックエンドからデータの結果(レスポンス)が帰ってきた場合に異なるオリジンという扱うを受けるため、ブロックされます。
シーケンス
@startuml
User ->> Frontend: ユーザー情報をフォームに入力
Frontend ->> Backend: OPTIONS /api/register\nOrigin: http://localhost:3001\nAccess-Control-Request-Method: POST\nAccess-Control-Request-Headers: Content-Type
Backend -->> Frontend: HTTP/1.1 204 No Content\nAccess-Control-Allow-Origin: http://localhost:3001\nAccess-Control-Allow-Methods: POST\nAccess-Control-Allow-Headers: Content-Type
Frontend ->> Backend: POST /api/register\nOrigin: http://localhost:3001\nContent-Type: application/json\n{email: user@example.com, password: ******}
Backend -->> Frontend: HTTP/1.1 201 Created\nAccess-Control-Allow-Origin: http://localhost:3001\nContent-Type: application/json\n{message: "User created successfully"}
Frontend -->> User: 登録完了メッセージ表示
@enduml
参考資料:
[https://developer.mozilla.org/ja/docs/Web/HTTP/CORS:title]
オリジンとは以下の3つの要素で構成されています:
- プロトコル(例:
httpやhttps) - ドメイン(例:
example.com) - ポート番号(例:
80、443)
これらの一つでも異なれば、異なるオリジンという扱いをされています。例えば、https://example.comとhttp://example.comは異なるオリジンです。
2. Ruby on RailsでのCORS設定
Ruby on RailsでCORSを設定するには、rack-corsというGemを使用します。このGemを使うことで、RailsアプリケーションにCORSヘッダーを簡単に設定できます。
2.1 rack-corsのインストール
まず、Gemfileにrack-corsを追加します。
gem 'rack-cors'
その後、以下のコマンドでインストールします。
bundle install
2.2 CORS設定の追加
次に、config/application.rbにCORSの設定を追加します。ここで、特定のオリジンからのリクエストを許可するように設定します。
module YourApp
class Application < Rails::Application
config.middleware.insert_before 0, Rack::Cors do
allow do
origins 'https://your-frontend-domain.com'
resource '*',
headers: :any,
methods: [:get, :post, :put, :patch, :delete, :options, :head],
credentials: true
end
end
end
end
-
origins: 許可するオリジンを指定します。 -
resource: リクエストできるリソースを指定します。*はすべてのリソースを許可します。 -
headers: 許可するリクエストヘッダーを指定します。:anyはすべてのヘッダーを許可します。 -
methods: 許可するHTTPメソッドを指定します。 -
credentials: クッキーや認証情報を含むリクエストを許可するかどうかを指定します。
3. Axiosでのリクエスト
ReactのフロントエンドからRuby on RailsのバックエンドにAPIリクエストを送る際、Axiosを使用します。このとき、認証情報(クッキーなど)を含めるためにwithCredentialsオプションを設定する必要があります。
3.1 Axiosのリクエスト例
以下のコードは、ユーザー登録時にAPIリクエストを送信する例です。
axios.post('http://localhost:3000/auth', {
email: 'test@gmail.com',
password: 'testtest',
password_confirmation: 'testtest',
confirm_success_url: 'http://localhost:3000/signin'
}, {
withCredentials: true // クッキーを含めるための設定
})
.then(response => {
console.log(response.data);
})
.catch(error => {
console.error('Error:', error);
});
ここで、withCredentials: trueを設定することで、ブラウザはクッキーをリクエストに含めます。このオプションを使用する場合、サーバー側でもcredentials: trueの設定が必要です。
多分これでできるはず
Discussion