小原 達也/ 2023年 10月 13日/ 技術

こんにちは!小原です。

先日遭遇した Django REST framework の CORS エラーで行った対策方法を共有します。

私の場合、無料版の ngrok の初回アクセス時に表示される Welcome ページが原因だったようです。

本記事では CORS エラーの対策方法を中心に、周辺知識も解説します。

似たようなエラーでお悩みの方は、ぜひ参考にしていただければと思います。

解決策

以下の2つを実装することで、CORS エラーを解消できました。

  1. リクエストヘッダーの追加
  2. django-cors-header の使用

1.リクエストヘッダーの追加

リクエストヘッダーとして追加することで CORS エラーが消えました。

{
    ngrok-skip-browser-warning: Value
}

詳しくは後述しますが、上記ヘッダーをつけることで ngrok の Welcome ページをスキップできます。

2.django-cors-header の使用

✓ ライブラリの役割


事前に設定した URL からのリクエストに対して、"access-control-allow-origin" ヘッダーを付与します。

このヘッダーの付与により、APIサーバー側は特定の URL からのアクセスを許可できます。

一方で、クライアント側は異なる URL にある API へのアクセスがブラウザ上で許可されます。

※ 上記は正確には「URL」ではなく「オリジン」となります。
>> 詳しくはこちら

✓ ライブラリのインストール

# pip の場合
pip install django-cors-headers

# poetry の場合
poetry add django-cors-headers

✓ settings.py

settings.py に対して以下を追加します。

INSTALLED_APPS = [
    # その他のAPPS
    "corsheaders",  # 追加
]

MIDDLEWARE = [
    "corsheaders.middleware.CorsMiddleware", # 追加
    "django.middleware.common.CommonMiddleware",
    # その他のAPPS
]

# 特定オリジンに access-control-allow-origin ヘッダーを追加
CORS_ALLOWED_ORIGINS = [
    "https://example.com",
]

MIDDLEWARE は上から下に実行していくので、記載順には注意が必要です。

今回の corsheaders.middleware.CorsMiddleware は一般的に CommonMiddleware の前に配置します。


【補足】

以下のコードですべてのオリジンを受け入れることもできます。

CORS_ALLOW_ALL_ORIGINS = True

この場合には CORS_ALLOWED_ORIGINS は不要です。

CORS エラー発生時の構成

構成
CORS エラー発生時の構成を簡単にご説明します。

  • 既存 Web サービス内の JavaScript fetch() 関数より、APIリクエストを行う
  • 無料版の ngrok を使用
  • API は Django REST framework で構築

問題の所在

結論として、以下のような Welcome ページが原因で CORS エラーが発生していたようです。
ngrok

通常であれば ngrok に向けて送信されたリクエストはそのまま Django REST framework に飛びます。
ところが、特定の環境ではこの Welcome ページが立ちはだかり CORS エラーが発生するということのようです。

なお、上記画面は無料版の ngrok で初回起動時に表示されます。

ngrok http 8000

こちらのコマンド実行後に、発行された URL にアクセスすると表示されるものです。

対策方法としては、以下の3つが考えられます。

  • リクエストヘッダーを追加する(>> 前述の方法
  • 有料版の ngrok にアップグレードする
  • ngrok を利用せずサーバーにデプロイする

Welcome ページの "To remove this page:" に対策方法の記載があります。

fetch() 関数でヘッダーを付与しても CORS エラーが発生し続ける場合

ブラウザ側でヘッダーを付与させる方法もあります。

例えば Chrome ブラウザの拡張機能 "ModHeader" を使うと、簡単にリクエストヘッダーを追加できます。

>> ModHeader - Modify HTTP headers

使い方は、インストール後に以下のように設定するだけです。

modheader

オリジンとは?

オリジンは URL とかなり近い概念です。

以下のような「スキーム + ホスト名 + ポート名」のまとまりがオリジンと呼ばれています。

オリジン

一方で、URL はオリジンの要素に加えて、パスやクエリパラメータを含んだ概念になります。
ex) https://www.example.com:80/path/to/resource?key=value#section

スキームとホスト名、ポートを含む点では共通していますが、そのほかの要素も含む概念が URL ということになります。

お知らせ

弊社は通年通して、一緒に働く仲間を募集しています。
興味を持たれた方がいらっしゃいましたら、以下よりご連絡をお待ちしております!
>> 中途採用募集要項
>> お問い合わせ