0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Django REST frameworkでpreflight requestが上手くいかない

Posted at

概要

※ 調査中。未解決です。暫定的な方法で解決しています。

フロント側からaxios.post でDjango(REST framework)にPOSTリクエストを送ると、Response to preflight request doesn't pass access control となってしまう。ajaxで送ってみたところ、正常にレスポンスが返ってきました。
色々試してみた結果、おそらくaxiosかdjango-cors-headerの使い方が悪そうです。

環境

  • Django 3.0.3
  • djangorestframework 3.11.0
  • django-cors-header 3.2.1
  • heroku

経緯

Django REST frameworkで作ったAPIを、Vue.jsで作った画面から呼び出して使うアプリケーションを作ろうとしておりました。某イベント開催に向け、便利なLINEアプリを作るためです。

Django REST frameworkでviewの作成

本家のチュートリアルをChapter3 くらいまで呼んで、簡単なviewを作成しました。
そして、ブラウザからAPIが想定通り動作することを確認。

django-cors-headerでCORSの設定

フロント側にVue.jsを使うため、CORSを許可します。

django-cors-headerで以下のように設定。
これによって、GETリクエストが通るようになりました。
しかし、POSTの時に送られるpreflight requestが正常に帰ってこない...

settings.py
# 変更部のみ抜粋
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app.apps.AppConfig',
    'rest_framework',
    'corsheaders'  # 追加
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'corsheaders.middleware.CorsMiddleware',  # 追加
    'django.middleware.common.CommonMiddleware',  # 追加
]
CORS_ORIGIN_WHITELIST = [
    'http://localhost:3000',  # フロントのサーバー
]

調査

preflight requestの行き先

preflight requestは、optionsで飛ぶようなので、APIサーバ側でoptionsリクエストが受け取れないようになっているのかもしれません。
そこで当該viewにoptionsを処理する部分を明示的に作り、Pycharm のデバッガでOPTIONSリクエストの行き先を確認してみます。

views.py
from rest_framework.views import APIView

# --- 中略 ---

class ClassBasedView(APIView):

    def post(self, request, format=None):
        # 処理

    def options(self, request, format=None):
        # 処理

viewsのaxios.post からのリクエストは、optionsの部分には到達していない様子。
しかし、curlでリクエスト送ると、optionsに到達します。
また、viewを関数ベースのものに変えてみても状況は同じでした。

ということは、django-cors-headerの使い方がどこか間違っているのでしょうか。。。

axiosの調査

一方で、試しにajaxでpostリクエストを送ってみると、正常にレスポンスが帰ってきました。
Django側のログを見てみると、OPTIONSリクエストは受け取っていない模様。
つまり、preflight requestの受け渡しが上手くいっていないようです。

// headerの設定
axios.defaults.headers.post['Access-Control-Allow-Origin'] = 'http://localhost:3000';
axios.defaults.baseURL = 'http://localhost:3000';
axios.defaults.headers.post['Content-Type'] = 'application/json;charset=utf-8';

axios.post(url, params) // こっちはだめ

$.ajax({url:url, type:'POST', data: params}) // こちらはリクエスト成功

まとめと今後

ajaxでデータ取得できたので、当面はajax使って開発を進めることにしました
(コロナショックでアプリ自体が不要になってしまいました...)

今後は、以下を調べてみようと思います。

  • Djangoでpreflight requestがどう処理されるのか(django-cors-header の詳細な使い方)
  • axiosでpreflight requestがどうやって送られるのか
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?