1. やりたいこと
Django REST frameworkで作ったAPIについて、Reactで作成したSPAからGETリクエストを送ったところ、以下のようなエラーがでました
Access to fetch at 'http://127.0.0.1:8000/articles/' from origin 'http://127.0.0.1:5173' 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. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
CORS policyによりブロックされたとありますので原因は許可されていないクロスオリジンからのデータ取得がDjangoによりブロックされているのだと分かります
本記事ではこれを解決する方法をまとめます
2. CORSとは
CORSとはCross-Origin Resource Sharingの略で、OriginはURL+portのことですから、CORSは異なるOriginへのリソース共有を示す言葉です。悪意のあるサイトが他のサイトのデータを不正に取得するクロスサイトリクエストフォージェリ(CSRF)のような攻撃を防ぐためにブラウザにはこれをブロックする仕組みが標準適用されているので、適切に設定せずにAPIを取りに行くと先ほどのようなエラーが出ます
例えばCookieによってログインが維持されている状態のままで悪意のあるサイトを踏んだとき、悪意のあるサイトがログインしないと読めない情報を取得してよそに送ってしまうのを防ぐというような目的で、原則として別Originからの情報取得をブラウザが禁止しているわけです
その為、今回のように別OriginにあるサーバーのAPIを取得する際には、APIサーバー側でどのOriginからのアクセスを許可するか設定しておく必要があります。実際に取得する際にはブラウザがAPIサーバーから許可するOriginの情報を書いたCORSヘッダーを受け取って、現在のOriginが許可されていればAPIサーバーにリクエストを実行するという手順でこれを実現します
3. django-cors-headersパッケージをインストールする
Django側でCORSヘッダーを扱えるようにするパッケージをインストールします
pip install django-cors-headers
4. settings.pyに設定を書く
4-1. INSTALLED_APPSに追加
以下でDjangoがcorsheaderを使うようになります
INSTALLED_APPS = [
...
'corsheaders',
...
]
4-2. MIDDLEWAREを追加
ミドルウェアにCorsMiddlewareとCommonMiddlewareを追加します
MIDDLEWARE = [
...
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
...
]
4-3. CORSポリシーを設定
特定のOriginを許可する場合
許可するOriginをリストで書いていけば許可してくれます
CORS_ALLOWED_ORIGINS = [
'http://127.0.0.1:5173',
]
すべてのOriginを許可する場合
一般公開するAPIのような場合は以下ですべてのOriginを許可しちゃいます
ウェブアプリのバックエンドとして使う用途だとこちらは使わないと思います
CORS_ALLOW_ALL_ORIGINS = True # すべてのオリジンからのアクセスを許可
5. 再起動する
あとはDjangoを再起動したら完成です