夕蛙のなく頃に

データアナリストとして学んだことや趣味で勉強し始めたIoTをアウトプットする

localhostに立てたFlaskのAPIをlocalhostのVueから叩いて表示する

これなに

webアプリを作る際に、バックエンドにFlaskのAPIを立てて、フロントエンドのVueから叩く構成にしました。

テスト用にとりあえずFlaskのAPIlocalhostに立てて、localhostのVueから叩いたところ、ブラウザのconsoleに以下のようなエラーが出ました。

Access to XMLHttpRequest at 'http://127.0.0.1:5000/' from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

これを解決したい。

結論

Python3の環境では以下が一番手っ取り早いそう。

from flask import Flask
from flask_cors import CORS

app = Flask(__name__)
CORS(app)

再現ソース

github.com

環境

$ python --version
Python 3.6.4 :: Anaconda, Inc.

$ pip list
Package      Version
------------ -------
Click        7.0    
Flask        1.0.2  
Flask-Cors   3.0.7  
itsdangerous 1.1.0  
Jinja2       2.10.1 
MarkupSafe   1.1.1  
pip          19.0.3 
setuptools   28.8.0 
six          1.12.0 
Werkzeug     0.15.2 

エラーの意味(クロスドメイン問題)

今回のエラーはCORSという仕組みによって起こったものです。

オリジン間リソース共有Cross-Origin Resource Sharing (CORS) は、追加の HTTP ヘッダーを使って、あるオリジン (ドメイン) で動いているウェブアプリケーションが、異なるオリジンのサーバーのリソースにアクセスできるようにする仕組みです。

オリジン間リソース共有 (CORS) - HTTP | MDN

すなわち、ドメインが異なるサーバーのリソース(クロスドメイン)にアクセスしようとしたが、そのサーバは異なるサーバーからのアクセスを許可していないから起こったエラーです。

APIのレスポンスヘッダーに Access-Control-Allow-Origin: *Access-Control-Allow-Origin: 127.0.0.1 のように許可するドメインを指定する必要があります。

それを手っ取り早く付与してくれるのが、上記解決法というわけです。

localhost同士なのにどうして?

ドメインが異なるという判定は、以下の基準で行われます。

  • プロトコルが異なる(httpとhttpsも異なると判定される)
  • ホスト名が異なる
  • (ポート番号が明示されている場合)ポート番号が異なる

CORS(Cross-Origin Resource Sharing)について整理してみた | DevelopersIO

今回は、アクセス元が http://127.0.0.1:8080、アクセス先が http://127.0.0.1:5000 であり、ポート番号が異なるため、クロスドメインと判定されました。

参考記事

オリジン間リソース共有 (CORS) - HTTP | MDN
CORS(Cross-Origin Resource Sharing)について整理してみた | DevelopersIO