「フロントエンドの開発はReact.js」、「APIの開発はExpress」で開発を行なっているときに発生したCORS関係のエラーに非常に苦しめられたので、その解決方法をメモしておきたいと思います。
発生したエラー
Chromeで動作確認をしていたところ、以下のようなエラーメッセージが表示されました。
Access to XMLHttpRequest at
'HerokuにデプロイしたAPI(Expressで開発)のURL' from origin 'http://localhost:3000'
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.
見ての通り、CORS関係のエラーです。
「リクエストのリソースに'Access-Control-Allow-Origin'ヘッダーがありません」
とのことなので、Express側で'Access-Control-Allow-Origin'の設定をしてあげる必要があります。
Express(API)側でやったこと
「Expressで用意しているレスポンスの処理全てに"Access-Control-Allow-Origin"を設定する」
という方法もあるようですが、こちらは手間がかかる方法なのでやめました。
それよりも、Expressで用意されているミドルウェアを利用すれば簡単に設定できます。
import express from 'express';
import cors from 'cors';
const app = express();
const corsOptions = {
origin: 'http://localhost:3000', // 許可したいオリジンを指定
credentials: true, // レスポンスヘッダーにAccess-Control-Allow-Credentialsを追加。ユーザー認証等を行う場合は、これがないとブラウザがレスポンスを捨ててしまうそう。
optionsSuccessStatus: 200 // レスポンスのHTTPステータスコードを「200(成功)」に設定
}
app.cors(corsOptions)
ちなみに、最後の行を「app.cors( )」のように「( )」内を空にした場合は、「全てのオリジンを許可する」という意味になり、危険です。そのため、許可したいオリジンを上記のコードのように設定した方が安全です。
参考記事はこちら: expressでCORSエラーが起きたらcorsで解決しよう
React.js側でやったこと
しかし、このままではエラーは解決せず、Same-Origin-Policy(同じオリジン同士だけがリソースを共有できるようにするというセキュリティの仕組み)に引っかかっています。
そのため、Same-Origin-Policyを回避するために、React.js側のpackage.jsonに、proxyの設定を行う必要があります(プロジェクトをcreate-react-appで開発していることが前提)。
例えば、
・APIサーバー(Express)が"https://example.herokuapp.com"、
・ローカルの開発サーバーが"https:localhost:3000"
だとすると、以下のように設定します。
"proxy": "https://example.herokuapp.com",
上記の設定を行うことで、今回のCORSを解決することができました。
例えば、React側から「axios.get(/books
)」を実行した場合、ブラウザが「http://localhost:3000/books」にリクエストを送り、開発サーバが「https://example.herokuapp.com/books」にproxyします。
この時、ブラウザから見れば「http://localhost:3000/books」にアクセスしているように見えるのでSame-Origin-Policyに引っかからないとのことです。
このSamaOrigin回避の仕組みに関しては、以下の記事がわかりやすかったです。
以上により、私はReact.js × Expressで発生したCORSエラーを解決することができました。
こういったCORSエラーは初心者にとってつまづきやすいポイントのようなので、非常に勉強になりました。
ここまで読んでいただきありがとうございました。
参考にさせていただいた記事