やりたいこと
CORSエラーを解消したい
状況
- dockerで立てたバックエンドとフロントエンドの通信においてCORSエラーが発生する。
- CORSの設定はバックエンド(FastAPI)に設定済み
- IPアドレスをホストマシンのIPにバインドし、LAN内の端末からアクセスできるようにしたのでallow_originsをワイルドカードに変更した
調査
何が悪いか分からなかったのでdockerのポート設定とFastAPIのコードとどちらが悪いか切り分けることから始めた。結果としては、dockerに不備はなくFastAPI側ということが分かった。
色々ググったが結局わからなかったので開発者ツールでエラーを確認すると理由が載ってた。
<以下エラー文>
Access to fetch at 'http://hoge:8000/api/login' from origin 'http://hoge:5173' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'.
原因
クレデンシャルモードだったためワイルドカードが使えずアクセスチェックで不合格となっていた。
# エラーを出していたコード(バックエンド)
app.add_middleware(
CORSMiddleware,
allow_origins = ["*"], #元々は"http:localhost:8000"を指定していた
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# 正しいコード(バックエンド)
app.add_middleware(
CORSMiddleware,
allow_origins = ["http://hoge:1234"], # originを指定
allow_credentials=True, #ここがTrueならワイルドカードは使えない
allow_methods=["*"],
allow_headers=["*"],
)
// エラーを出していたコード(フロントエンド(React))
const onSubmit: SubmitHandler<LoginForm> = (data) => {
fetch('http://hoge:8000/api/login', {
method: "POST",
credentials: "include", //ここがincludeならワイルドカードは使えない
headers: {
"Content-Type": "application/json",
},
解決策
ワイルドカードを使わず、オリジンを指定する。
ワイルドカードを使いたいならクレデンシャルモードを使わない。
(ただしCookieを使ったログインなどはできなくなる)
最後に
解決まで3時間程度かかってしまったが、答えはすぐ近く(ブラウザのコンソール)にあった。エラー文を最初にしっかり読んでおけばすぐに解決できたはず...
今後はまずエラーから確認しよう(^_^;)