Help us understand the problem. What is going on with this article?

FastAPIでCORSを回避

はじめに

FastAPIを使っていてCORSの問題にぶち当たり
2時間ほど詰まってしまったので、他に困っている人に向けて解決方法を残します。

問題のソースコード

問題のソースコードはこのようになっています。
今回は公式でも取り上げられているようなサンプルプログラムを参考に作っています。
https://fastapi.tiangolo.com/tutorial/first-steps/

main.py
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しか検証していません
main.py
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}

今回、解決にあたって、こちらの方が実装しているコードを参考にしました。

https://github.com/tiangolo/full-stack-fastapi-postgresql/blob/b96d78db99d8c4f37f0df64df587ffebda4bfc56/%7B%7Bcookiecutter.project_slug%7D%7D/backend/app/app/main.py

おわりに

CORSについてエラーが起きたとき、当初はCORSについてまったく知識がなかったので、どう対処してよいかわかりませんでしたが、フィックスしていくに当たって、理解を深めることができよかったです。ただ、2時間消費してしまったのはつらい...
少しでも他の方のお役に立てればと思います。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした