はじめに
FastAPIを使っていてCORSの問題にぶち当たり
2時間ほど詰まってしまったので、他に困っている人に向けて解決方法を残します。
問題のソースコード
問題のソースコードはこのようになっています。
今回は公式でも取り上げられているようなサンプルプログラムを参考に作っています。
https://fastapi.tiangolo.com/tutorial/first-steps/
from fastapi import FastAPI
app = FastAPI()
@app.get("/users/")
def read_users():
return {"id": 1, "name": "taro"}
@app.get("/users/{user_id}")
def read_user(user_id: int):
return {"user_id": user_id}
FastAPIの起動
$ uvicorn main:app --reload --host 0.0.0.0 --port 8000
http://localhost:8000 で待機します
症状
FastAPIが待機しているhttp://localhost:8000
に対して
アプリケーションのhttp://localhost:8080
からアクセスすると
下記のようなエラーがchromeのコンソール上で確認されました。
Access to fetch at 'http://localhost:8000/users/' from origin
'http://localhost:8080' has been blocked by CORS policy:
No 'Access-Control-Allow-Origin' header is present on the requested resource.
If an opaque response serves your needs, set the request's mode to
'no-cors' to fetch the resource with CORS disabled.
エラーを見てみるとCORSのポリシーによってhttp://localhost:8080
はブロックされているようなので、
どうやらサーバ側でアプリケーションURLを許可するかCORSを回避してあげれば良さそうです。
解決方法
通常であれば、サーバからのレスポンスヘッダーに
Access-Control-Allow-Origin: *
を追加してあげればよいのですが、
FastAPIの場合は直接ヘッダー情報を追加するのではなく、下記のような対応をとります。
- 追記
allow_origins=["*"]のみだと、POSTのとき怒られるので、
3つほどパラメータを追加しました。
これで、全メソッドに対応できると思います(POST,PUTしか検証していません
from fastapi import FastAPI
from starlette.middleware.cors import CORSMiddleware # 追加
app = FastAPI()
# CORSを回避するために追加(今回の肝)
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True, # 追記により追加
allow_methods=["*"], # 追記により追加
allow_headers=["*"] # 追記により追加
)
@app.get("/users")
def read_users():
return {"id": 1, "name": "taro"}
@app.get("/users/{user_id}")
def read_user(user_id: int):
return {"user_id": user_id}
今回、解決にあたって、こちらの方が実装しているコードを参考にしました。
おわりに
CORSについてエラーが起きたとき、当初はCORSについてまったく知識がなかったので、どう対処してよいかわかりませんでしたが、フィックスしていくに当たって、理解を深めることができよかったです。ただ、2時間消費してしまったのはつらい...
少しでも他の方のお役に立てればと思います。