現在、ポートフォリオ を作成中です。
フロントをReact バックエンド をrails-apiモードで作成し、それぞれherokuへデプロイしたのですが、フロントのReactからAPIへ通信するとCORSのエラーが出てしまい、通信できません。
ローカルで試したのですが、ローカルだとうまく行くので、理由が全くわかりません。
CORSに関しては結構調べ、学習はしたつもりですが...
(なお、Dockerfileとheroku.ymlで環境変数を渡しています)
原因や解決策などを教えていただけるとありがたいです。
エラー文
通信後、検証ツールのnetworkのコンソール
Access to XMLHttpRequest at 'https://バックエンド アプリ名/api/v1/login' from origin 'https://フロントエンドアプリ名.herokuapp.com' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. xhr.js:187 POST https://アプリ名/api/v1/login net::ERR_FAILED
環境変数でローカルと本番環境のURLどちらもいけるようにしています。
cors.rb
1Rails.application.config.middleware.insert_before 0, Rack::Cors do 2 allow do 3 origins ENV["API_DOMAIN"] || "" 4 5 resource "*", 6 headers: :any, 7 methods: [:get, :post, :put, :patch, :delete, :options, :head], 8 credentials: true 9 end 10end
herokuの環境変数の確認
$ echo ${API_DOMAIN} アプリ名.herokuapp.com
→フロントエンド側のURLはしっかり登録されています
参考
Docker file api側
FROM ruby:3.0.0 ARG WORKDIR ARG API_DOMAIN ENV LANG C.UTF-8 \ TZ Asia/Tokyo\ HOME =/${WORKDIR} \ API_DOMAIN =${API_DOMAIN} RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - \ && echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list \ && apt-get update -qq \ && apt-get install -y nodejs yarn \ && mkdir /cooklog WORKDIR /cooklog COPY Gemfile /cooklog/Gemfile COPY Gemfile.lock /cooklog/Gemfile.lock RUN bundle install COPY . /cooklog/ COPY entrypoint.sh /usr/bin/ RUN chmod +x /usr/bin/entrypoint.sh ENTRYPOINT ["entrypoint.sh"] EXPOSE 3000 CMD ["rails", "server", "-b", "0.0.0.0"]
heroku.yml
setup: addons: - plan: cleardb config: RACK_ENV: production RAILS_ENV: production RAILS_LOG_TO_STDOUT: enabled RAILS_SERVE_STATIC_FILES: enabled build: docker: web: Dockerfile config: WORKDIR: app run: web: bundle exec puma -C config/puma.rb
試したこと
・ローカルでのcorsのエラーが出ないことを確認
・環境変数を使わず、直接本番環境用のURLを記載したり↓
cors.rb
1Rails.application.config.middleware.insert_before 0, Rack::Cors do 2 allow do 3 origins ENV["API_DOMAIN"] || "https://アプリ名.heroku........" 4 5 resource "*", 6 headers: :any, 7 methods: [:get, :post, :put, :patch, :delete, :options, :head], 8 credentials: true 9 end 10end
しかし、何も変わりませんでした。
思いつく原因がもうなく、他アドバイスなどいただけると幸いです。
追記
リクエスト時のヘッダー内容
Provisional headers are shown Learn more Accept: application/json, text/plain, */* Content-Type: application/json Referer: https://フロントアプリ名/ sec-ch-ua: " Not;A Brand";v="99", "Google Chrome";v="97", "Chromium";v="97" sec-ch-ua-mobile: ?1 sec-ch-ua-platform: "Android" User-Agent: Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Mobile Safari/537.36
フロント側のaxios通信部分
/* eslint-disable react-hooks/exhaustive-deps */ import { useCallback, useState } from "react"; import axios from "axios"; import { useHistory } from "react-router-dom"; import { useMessage } from "./useMessege"; import { useLoginUser } from "./useLoginUser" import { loginURL } from '../urls/index' export const useAuth = () => { const history = useHistory(); const { showMessage } = useMessage(); const { setLoginUser } = useLoginUser(); const [loading, setLoading] = useState(false); const login = useCallback((data) => { setLoading(true); //ローディングアイコンをtrueに axios.post(loginURL, { user: { email: data.email, password: data.password, } }, { withCredentials: true } ).then(response => { if (response.data.logged_in) { setLoginUser(response.data) showMessage({ title: "ログインしました", status: "success" }); const user_id = response.data.user.id history.push(`/users/${user_id}`); } // 認証できなかった時のエラー else if (response.data.status === 401) { showMessage({ title: `${response.data.errors}`, status: "error" }); } // うまくpostできなかった時のエラー }).catch((e) => { showMessage({ title: "認証できませんでした。再度リロードなどを行いやり直して下さい", status: "error" }); setLoading(false); }) }, [history, showMessage, setLoginUser]); return { login, loading }; };

回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。