Flaskを使用したクロスオリジンリソースシェアリングの解決


86

次のajax投稿リクエストの場合Flaskフラスコ内のajaxから投稿されたデータをどのように使用できますか?):

$.ajax({
    url: "http://127.0.0.1:5000/foo", 
    type: "POST",
    contentType: "application/json",
    data: JSON.stringify({'inputVar': 1}),
    success: function( data ) { 
        alert( "success" + data );
    }   
});

私が取得Cross Origin Resource Sharing (CORS)エラー:

No 'Access-Control-Allow-Origin' header is present on the requested resource. 
Origin 'null' is therefore not allowed access. 
The response had HTTP status code 500.

次の2つの方法で解決しようとしましたが、どれもうまくいかないようです。

  1. Flask-CORSの使用

これは、クロスオリジンAJAXを可能にするFlask処理の拡張機能ですCORS

このソリューションを使用している私のpythonServer.py

from flask import Flask
from flask.ext.cors import CORS, cross_origin

app = Flask(__name__)
cors = CORS(app, resources={r"/foo": {"origins": "*"}})
app.config['CORS_HEADERS'] = 'Content-Type'

@app.route('/foo', methods=['POST','OPTIONS'])
@cross_origin(origin='*',headers=['Content-Type','Authorization'])
def foo():
    return request.json['inputVar']

if __name__ == '__main__':
    app.run()
  1. 特定のFlaskデコレータを使用する

これは、デコレータをデコレートする関数を許可するデコレータを定義する公式のFlaskコードスニペットCORSです。

このソリューションを使用している私のpythonServer.py

from flask import Flask, make_response, request, current_app
from datetime import timedelta
from functools import update_wrapper

app = Flask(__name__)

def crossdomain(origin=None, methods=None, headers=None,
                max_age=21600, attach_to_all=True,
                automatic_options=True):
    if methods is not None:
        methods = ', '.join(sorted(x.upper() for x in methods))
    if headers is not None and not isinstance(headers, basestring):
        headers = ', '.join(x.upper() for x in headers)
    if not isinstance(origin, basestring):
        origin = ', '.join(origin)
    if isinstance(max_age, timedelta):
        max_age = max_age.total_seconds()

    def get_methods():
        if methods is not None:
            return methods

        options_resp = current_app.make_default_options_response()
        return options_resp.headers['allow']

    def decorator(f):
        def wrapped_function(*args, **kwargs):
            if automatic_options and request.method == 'OPTIONS':
                resp = current_app.make_default_options_response()
            else:
                resp = make_response(f(*args, **kwargs))
            if not attach_to_all and request.method != 'OPTIONS':
                return resp

            h = resp.headers

            h['Access-Control-Allow-Origin'] = origin
            h['Access-Control-Allow-Methods'] = get_methods()
            h['Access-Control-Max-Age'] = str(max_age)
            if headers is not None:
                h['Access-Control-Allow-Headers'] = headers
            return resp

        f.provide_automatic_options = False
        return update_wrapper(wrapped_function, f)
    return decorator

@app.route('/foo', methods=['GET','POST','OPTIONS'])
@crossdomain(origin="*")
def foo():
    return request.json['inputVar']

if __name__ == '__main__':
    app.run()

その理由を教えていただけますか?


あなたは理解しましたか?私はまったく同じ問題に
遭遇します:

これは古い質問ですが、念のために言っておきます。Flaskサーバーを再起動しましたか?また、すべてが正確に正しいと思っていても、なぜ同じエラーが発生するのか疑問に思いました。結局のところ、サーバーを実際に有効にするには、サーバーを再起動する必要あります
Juha Untinen 2017年

回答:


53

コードを少し変更した後、それはチャンピオンのように機能しました

# initialization
app = Flask(__name__)
app.config['SECRET_KEY'] = 'the quick brown fox jumps over the lazy   dog'
app.config['CORS_HEADERS'] = 'Content-Type'

cors = CORS(app, resources={r"/foo": {"origins": "http://localhost:port"}})

@app.route('/foo', methods=['POST'])
@cross_origin(origin='localhost',headers=['Content- Type','Authorization'])
def foo():
    return request.json['inputVar']

if __name__ == '__main__':
   app.run()

*をlocalhostに置き換えました。私は多くのブログや投稿を読んでいるので、特定のドメインへのアクセスを許可する必要があります


2
ブループリントを使用している場合は、各ブループリントにCORS()を追加する必要があります。例:my_blueprint = Blueprint( 'my_bp_name'、name、url_prefix = "/ my-prefix")CORS(my_blueprint)
BLang

90

あなたは簡単で結果を得ることができます:

@app.route('your route', methods=['GET'])
def yourMethod(params):
    response = flask.jsonify({'some': 'data'})
    response.headers.add('Access-Control-Allow-Origin', '*')
    return response

1
クロスドメイン実装を追加する方が良いです!
Florescuカタリン

シンプルで効果的
Anthony

4
鮮やかさ!私は同意します、シンプルで効果的です。IMOは回答を受け入れる必要があります
PALEN 2017年

3
@Salvador Dali-jsonオブジェクトだけでなくテンプレートをレンダリングする場合、クロスオリジンを許可する適切な方法を知っていますか?すなわち内のコードの最後の行はyourMethod次のとおりです。return render_template('template.html',some_var = response)
マッテオ

3
これはpostメソッドで使用できますか?ファイルのアップロード方法を試しましたが失敗しました。
W.Leto

64

さて、私は同じ問題に直面しました。このページにたどり着く可能性のある新規ユーザー向け。公式ドキュメントに従ってください。

フラスココアを取り付けます

pip install -U flask-cors

次に、アプリの初期化後flask-cors、デフォルトの引数で初期化します。

from flask import Flask
from flask_cors import CORS

app = Flask(__name__)
CORS(app)

@app.route("/")
def helloWorld():
   return "Hello, cross-origin-world!"

これにより、次のエラーが発生します。「原点からのmy_domain」でのXMLHttpRequestへのアクセス 127.0.0.1:5000CORSポリシーによってブロックされました。プリフライトリクエストへの応答がアクセス制御チェックに合格しません:「Access-Control-Allow- Origin 'ヘッダーには複数の値' 127.0.0.1:5000、* 'が含まれていますが、許可されるのは1つだけです。
humblePilgrim

私にはうまくいきません。stackoverflow.com/questions/59652099/...
WPマクニール

私にも効くTks!
ホセ

私のために働いた!
どうも

設定方法Access-Control-Max-Ageflask_cors
DragonKnight

5

これが答えになるかもしれません。今日も同じ問題が発生しましたが、予想以上に問題はありませんでした。CORS機能を追加した後、コードが正しい場合でも変更を有効にするには、Flaskサーバーを再起動する必要あります(ctrl + c-> python manage.py runserver、または使用する方法))。そうしないと、CORSはアクティブインスタンスで機能しません。

これが私にとってどのように見え、どのように機能するかです(Python 3.6.1、Flask 0.12):

factory.py

from flask import Flask
from flask_cors import CORS  # This is the magic


def create_app(register_stuffs=True):
    """Configure the app and views"""
    app = Flask(__name__)
    CORS(app)  # This makes the CORS feature cover all routes in the app

    if register_stuffs:
        register_views(app)
    return app


def register_views(app):
    """Setup the base routes for various features."""
    from backend.apps.api.views import ApiView
    ApiView.register(app, route_base="/api/v1.0/")

views.py

from flask import jsonify
from flask_classy import FlaskView, route


class ApiView(FlaskView):
    @route("/", methods=["GET"])
    def index(self):
        return "API v1.0"

    @route("/stuff", methods=["GET", "POST"])
    def news(self):
        return jsonify({
            "stuff": "Here be stuff"
        })

私のReactアプリconsole.log:

Sending request:
GET /stuff
With parameters:
null
bundle.js:17316 Received data from Api:
{"stuff": "Here be stuff"}

4

を設定することに注意してください Access-Control-Allow-Origin多くの場合(このような場合)、Flask応答オブジェクトにヘッダーことは問題ありませんが、静的アセットを提供する場合(少なくとも本番環境では)効果がないことに。これは、静的アセットが前面のWebサーバー(通常はNginxまたはApache)によって直接提供されるためです。したがって、その場合は、FlaskではなくWebサーバーレベルで応答ヘッダーを設定する必要があります。

詳細については、ヘッダーの設定方法を説明した、しばらく前に書いたこの記事を参照してください。(私の場合、Font Awesomeアセットのクロスドメインサービングを実行しようとしていました)。

また、@ Satuが言ったように、JS AJAXリクエストの場合、特定のドメインに対してのみアクセスを許可する必要がある場合があります。静的アセット(フォントファイルなど)を要求する場合、ルールはそれほど厳しくなく、任意のドメインへのアクセスを許可する方が受け入れられていると思います。


3

私はArminRonacherによって提供されたデコレータをほとんど変更せずに使用しました(クライアントから要求されたヘッダーが異なるため)そしてそれは私にとってはうまくいきました。(アプリケーション/ jsonタイプを要求するリクエスターとしてangularを使用します)。

コードは以下の場所でわずかに変更されています、

from flask import jsonify

@app.route('/my_service', methods=['POST', 'GET','OPTIONS'])
@crossdomain(origin='*',headers=['access-control-allow-origin','Content-Type'])
def my_service():
    return jsonify(foo='cross domain ftw')

jsonifyはapplication / jsonタイプを送信します。それ以外の場合は、text / htmlになります。ヘッダーは、私の場合、それらのヘッダーのリクエストでクライアントとして追加されます

 const httpOptions = {
      headers: new HttpHeaders({
        'Content-Type': 'application/json',
        'Access-Control-Allow-Origin':'*'
      })
    };
    return this.http.post<any>(url, item,httpOptions)

2
デコレータへのリンクは死んでいる
ホセ・トマスTocino

2

注:cross_originの配置は正しく、依存関係がインストールされている必要があります。クライアント側では、消費しているデータサーバーの種類を必ず指定してください。たとえば、application / jsonまたはtext / html

私にとって、以下に書かれたコードは魔法をかけました

from flask import Flask,request,jsonify
from flask_cors import CORS,cross_origin
app=Flask(__name__)
CORS(app, support_credentials=True)
@app.route('/api/test', methods=['POST', 'GET','OPTIONS'])
@cross_origin(supports_credentials=True)
def index():
    if(request.method=='POST'):
     some_json=request.get_json()
     return jsonify({"key":some_json})
    else:
        return jsonify({"GET":"GET"})


if __name__=="__main__":
    app.run(host='0.0.0.0', port=5000)

なぜ同じこと(support_credentials = True)を行うのcross_originですか?
EzizDurdyyev20年


0

私は似たようなものでたくさん苦労しました。次のことを試してください。

  1. HTMLヘッダーを表示できるある種のブラウザプラグインを使用します。
  2. サービスへのURLを入力し、返されたヘッダー値を表示します。
  3. Access-Control-Allow-Originが唯一のドメインに設定されていることを確認してください。これはリクエストの発信元である必要があります。Access-Control-Allow-Originを*に設定しないでください。

これで問題が解決しない場合は、この記事をご覧ください。PHP上にありますが、CORSが機能するためにどのヘッダーをどの値に設定する必要があるかを正確に説明しています。

IE、Firefox、Chrome、Safariで動作するCORS

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.