質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Ruby on Rails 6

Ruby on Rails 6は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Amazon Route 53

Amazon Route 53 はAmazonが提供する、 可用性と拡張性に優れた ドメインネームシステム(DNS)サービスです。

CORS

CORSとはCross-Origin Resource Sharingの頭文字をとったもので、ブラウザがオリジン以外のサーバからデータを取得するシステムのことです。

AWS(Amazon Web Services)

Amazon Web Services (AWS)は、仮想空間を機軸とした、クラスター状のコンピュータ・ネットワーク・データベース・ストーレッジ・サポートツールをAWSというインフラから提供する商用サービスです。

React.js

Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

Q&A

0回答

5086閲覧

【環境:EC2、ALB、Route53】独自ドメインからAPIにアクセスするときにCORSエラーが発生する

gozikyu

総合スコア4

Ruby on Rails 6

Ruby on Rails 6は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Amazon Route 53

Amazon Route 53 はAmazonが提供する、 可用性と拡張性に優れた ドメインネームシステム(DNS)サービスです。

CORS

CORSとはCross-Origin Resource Sharingの頭文字をとったもので、ブラウザがオリジン以外のサーバからデータを取得するシステムのことです。

AWS(Amazon Web Services)

Amazon Web Services (AWS)は、仮想空間を機軸とした、クラスター状のコンピュータ・ネットワーク・データベース・ストーレッジ・サポートツールをAWSというインフラから提供する商用サービスです。

React.js

Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

0グッド

1クリップ

投稿2021/05/03 01:14

編集2021/05/04 04:53

やりたいこと

以下の構成でブラウザ上のreactからrails-apiにリクエストを送りたい

フロントエンド:react
バックエンド:rails
インフラ:AWS下記図

EC2にdockerをインストールして、docker-composeでreact、rails、nginxを起動しています。
イメージ説明
イメージ説明

困っていること

'Access-Control-Allow-Origin' header がないというCORSのエラーが発生しています。
例えば、reactで以下のコードの4行目でAPIにゲットリクエストをすると、コンソールで写真のようなエラーが発生します。

const guestSignIn = () => { axios .post( 独自ドメイン + ":3001" + "/login", { user: { email: "guest@gmail.com", password: "password", }, }, { withCredentials: true } ) .then((response) => { console.log("registration res", response); const createdId = response.data.user_id; console.log(createdId); props.login(); history.push({ pathname: "/users/" + createdId }); }) .catch((error) => { console.log("registration error", error); alert( "ゲストアカウントでログインできませんでした。通信環境をご確認ください。" ); }); };

イメージ説明

railsではapplication.rbでCROSの設定をしており、Access-Control-Allow-Originについても設定しています。
実際に、localhostや本番環境にIPアドレスにアクセスして、rails-apiにリクエストを送った際は、Access-Control-Allow-Originが正常に機能しています。

しかし、独自ドメインにアクセスしたときにのみ、Access-Control-Allow-Originのheaderがなくなってしまいます。

独自ドメインのときのみ、このような問題が起こるため、AWSのRoute53かALBでCORSの設定が別途必要なのかとも思い現在調べておりますが、該当するようなページを見つけられていません。

なぜ、このような事が起こるのか、知見ございます方がいらっしゃいましたら、アドバイスいただけないでしょうか。

よろしくお願いいたします。0. 番号リスト

application.rb

require_relative 'boot' require 'rails' # Pick the frameworks you want: require 'active_model/railtie' require 'active_job/railtie' require 'active_record/railtie' require 'active_storage/engine' require 'action_controller/railtie' require 'action_mailer/railtie' require 'action_mailbox/engine' require 'action_text/engine' require 'action_view/railtie' require 'action_cable/engine' # require "sprockets/railtie" require 'rails/test_unit/railtie' # Require the gems listed in Gemfile, including any gems # you've limited to :test, :development, or :production. Bundler.require(*Rails.groups) module Myapp class Application < Rails::Application # Initialize configuration defaults for originally generated Rails version. config.load_defaults 6.1 # Configuration for the application, engines, and railties goes here. # # These settings can be overridden in specific environments using the files # in config/environments, which are processed later. # # config.time_zone = "Central Time (US & Canada)" # config.eager_load_paths << Rails.root.join("extras") # Only loads a smaller set of middleware suitable for API only apps. # Middleware like session, flash, cookies can be added back manually. # Skip views, helpers and assets when generating a new resource. config.api_only = true config.middleware.insert_before 0, Rack::Cors do allow do origins 'http://localhost', 'https://独自ドメイン' resource '*', headers: :any, methods: %i[get post patch delete options], credentials: true end end config.hosts << '.example.com' config.hosts << '独自ドメイン' config.hosts << 'localhost' # セッションメソッドを有効にする config.middleware.use ActionDispatch::Cookies config.middleware.use ActionDispatch::Session::CookieStore config.middleware.use ActionDispatch::ContentSecurityPolicy::Middleware config.time_zone = 'Tokyo' config.active_record.default_timezone = :local config.action_dispatch.default_headers = { 'Access-Control-Allow-Credentials' => 'true', 'Access-Control-Allow-Origin' => if Rails.env.production? 'https://独自ドメイン' else 'http://localhost' end, 'Access-Control-Request-Method' => '*' } end end

追加

対症療法的ではありますが、上記問題を解決する事ができました。

変更点
ALBのターゲットを変更
変更前:独自ドメインのポート3001へのアクセスの転送先の設定はインスタンス(ポート3001)
変更後:独自ドメインのポート3001へのアクセスの転送先の設定はVPC内のインスタンスのプライベートIP(ポート3001)

変更前のターゲット
イメージ説明
変更後のターゲット
イメージ説明

問題は解決できたのですが、根本的理解はできていません。具体的には以下2点です。
・ターゲットの設定方法の違いでなぜ問題が解決したのか?
・変更後のターゲットのヘルスチェックでstatus403でエラーになっているのになぜ、アプリは正常に動作するのか?
(言い換えると、ブラウザのReactからリクエストを投げたときはなぜ403にならないのか?)

こちら、自分でも調べておりますが、わかる方いらっしゃいましたらご教示いただけると幸いです。

よろしくお願いいたします。

追加2

Route53のレコード設定
Aレコードにportfolio-elbというALBを設定しています
イメージ説明
ALBの設定画面
イメージ説明

ALBのヘルスチェックでEC2ポート3001の/gymsにアクセスした際のEC2のdocker上のログ 403になっている
イメージ説明

ブラウザからEC2ポート3001の/gymsにアクセスした際のEC2のdocker上のログ 304になっている
![イメージ説明]
イメージ説明

このことから、ALBのヘルスチェックはEC2に届いているが、ヘルスチェックの場合のみ403で弾かれていると考えております。

追加3

nginx.conf

# プロキシ先の指定 # Nginxが受け取ったリクエストをバックエンドのpumaに送信 upstream webapp { # ソケット通信したいのでpuma.sockを指定 server unix:///webapp/tmp/sockets/puma.sock; } server { listen 80; # ドメインもしくはIPを指定 server_name 独自ドメイン; access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log; # ドキュメントルートの指定 root /webapp/public; client_max_body_size 100m; error_page 404 /404.html; error_page 505 502 503 504 /500.html; try_files $uri/index.html $uri @webapp; keepalive_timeout 5; # リバースプロキシ関連の設定 location @webapp { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_pass http://webapp; } }

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yu_1985

2021/05/03 16:48

> 独自ドメイン + ":3001" + "/login" 前の質問を見るとAPIとしての役割をしているのはRailsかと思っているのですが、リクエストを送る先はこれであってるんでしょうか? そもそもの話をすると、Reactの開発サーバを立て続ける意味があるのか、というところになるんですが、話がそれるので一旦置いておきます。 unhealthyになっているということはALBからそのインスタンスに対してリクエストは飛んでいませんね。 にもかかわらずうまく表示できるということは、ALBを経由していない可能性がある気がしています。 ものすごく気になるのですが、Route53のレコードはちゃんとALBを指定していますか? 403になっている原因も、インスタンスの方のログから調べるべきでしょう。 どうでもいいですが、ALBがあるのもInternet GatewayがあるのもVPCの中なので図は微妙に正しくないです。
gozikyu

2021/05/04 00:19

yu_1985さん 前回に引き続きアドバイスいただきありがとうございます。 Q 前の質問を見るとAPIとしての役割をしているのはRailsかと思っているのですが、リクエストを送る先はこれであってるんでしょうか? A 私の認識としては、EC2のポート3001でrails-apiが動いている(正確にはポート3001で動いているnginxがrails-apiにリクエストを転送している)ので、独自ドメイン + ":3001" + "/login"という宛先にしておりました。 Q unhealthyになっているということはALBからそのインスタンスに対してリクエストは飛んでいませんね。 にもかかわらずうまく表示できるということは、ALBを経由していない可能性がある気がしています。 403になっている原因も、インスタンスの方のログから調べるべきでしょう。 A EC2のログを見るとALBからリクエストは受け取っているようです。 実際の画面を本文に追加いたします。 ヘルスチェックはポート3001の/gymsというアドレスへのレスポンスを見ています。 ブラウザから 独自ドメイン:3001/gyms にアクセスする(getリクエストをする)とEC2のログでは304となり、403で弾かれていません。 つまり、 ブラウザ→ALB→EC2 の場合は304 ALB→EC2 の場合派403 となっていると考えています。 どちらも結局はALBからのリクエストなので、違いはないはずなのですが、、 Q ものすごく気になるのですが、Route53のレコードはちゃんとALBを指定していますか? A Route53のAレコードはエイリアスによりALBを設定しています。 設定画面を本文に追加いたしました。
yu_1985

2021/05/04 03:22

> ブラウザからEC2ポート3001の/gymsにアクセスした際のEC2のdocker上のログ 念の為確認しますけど、ブラウザからEC2に直接アクセスしているわけではないですよね…? ヘルスチェックのログの時間帯とdocker上のログの時間帯が離れすぎていて、それらが同時に起こっているとはちょっとこれでは言えません。 むしろヘルスチェックだけリクエストが飛んでいて、クライアントからのリクエストを送っていないように思えるのですが。 そういえば、nginxのほうでヘッダを追加していますか? https://jogiranjith.github.io/blog/2016/07/27/cors-on-rails-and-nginx/ Healthyでないインスタンスにはクライアントからのリクエストは転送されません。 なのでヘルスチェックの段階で403になっていて、EC2インスタンスにはリクエストは届いていないと考えるべきでしょう。 403になっているのはヘルスチェックのやり方に問題があるか、EC2側にある何かで弾いてる可能性があります。
gozikyu

2021/05/04 05:03

>念の為確認しますけど、ブラウザからEC2に直接アクセスしているわけではないですよね…? ブラウザから、https://condots.net:3001/gyms にアクセスしております。(condots.netが今まで独自ドメインと記載していた部分です。) ALBのポート3001のリスナーの転送先をEC2のポート3001にしているのですが、これを変更すると、ブラウザから同様にhttps://condots.net:3001/gymsにアクセスしても表示されなくなりました。 つまり、ブラウザからアクセスした場合でもALBを経由していると考えています。 >そういえば、nginxのほうでヘッダを追加していますか? nginxではheaderは追加していませんでした。本文に現在のnginx.confを追加しました。 nginxにheaderの設定が必要ということなのでしょうか?(勉強不足で基礎的な質問ばかりで申し訳ありません。) nginx.confにもheaderを追加すると以下のようにheaderが2つあるというエラーが出てしまっているので現在修正中です。 The 'Access-Control-Allow-Origin' header contains multiple values 'https://condots.net, *', but only one is allowed. おっしゃるとおり、ヘルスチェックで403になっているとリクエストはALBから転送されないはずですよね、、、 まだ頂いたアドバイスをもとに自分で調査中ですが、取り急ぎ状況を報告させていただきます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問