web-dev-qa-db-ja.com

Flask AngularでのRESTfulクロスドメインの問題:PUT、OPTIONSメソッド

IPアドレスを変更する可能性のある少数のクライアントからのPUT要求を受け入れるREST Restfulの小さな書き込み専用Flask apiを開発しました。私のクライアントは、AngularJSフロントエンドを実行する組み込みChromiumクライアントです。彼らは単純な魔法の鍵を使って私のAPIで認証します-私の非常に限られた規模で十分です。

現在、APIのデプロイをテストしていますが、AngularクライアントがFlaskサービスにOPTIONS httpメソッドを送信しようとしています。その間、私のAPIは404で応答しています(OPTIONSハンドラーはまだ作成しておらず、PUTハンドラーのみを作成しているため)。 POSTまたはGETではないクロスドメインリクエストを送信する場合、AngularはサーバーでプリフライトOPTIONSメソッドを送信し、クロスドメインリクエストが受け入れられるようにします実際のリクエストを送信する前に。そうですか?

とにかく、Flask Restful APIへのすべてのクロスドメインPUTリクエストを許可するにはどうすればよいですか?以前に(非レストフル)Flaskインスタンスでクロスドマイオンデコレータを使用したことがありますが、APIにOPTIONSハンドラーも記述する必要がありますか?

38
b.b.

FlaskバックエンドをPUT応答のAccess-Control-Allow-Originヘッダーで応答するように書き直すことで問題を解決しました。さらに、Flask appは、HTTP RFCで読んだ内容に従ってオプションメソッドに回答します。

PUTメソッドの戻り値は次のようになります。

return restful.request.form, 201, {'Access-Control-Allow-Origin': '*'} 

私のOPTIONSメソッドハンドラは次のようになります。

def options (self):
    return {'Allow' : 'PUT' }, 200, \
    { 'Access-Control-Allow-Origin': '*', \
      'Access-Control-Allow-Methods' : 'PUT,GET' }

@tbicrは正しい:Flask OPTIONSメソッドに自動的に応答します。ただし、私の場合は、その応答でAccess-Control-Allow-Originヘッダーを送信していなかったので、私のブラウザ私は、クロスドメインリクエストが許可されていないことを示唆しているように見えるAPIから応答を受け取っていました。私は、オプションリクエストをオーバーロードし、ACAOヘッダーを追加し、ブラウザはそれで満足しているようで、OPTIONSをフォローアップしましたPUTも機能しました。

18
b.b.

Flask-CORS モジュールを使用すると、コードを変更せずにドメイン間リクエストを実行できます

from flask.ext.cors import CORS

app = Flask(__name__)
cors = CORS(app, resources={r"/api/*": {"origins": "*"}})

更新

Eric が提案したように、flask.ext.corsモジュールは非推奨になりました。次のコードを使用する必要があります。

from flask_cors import CORS

app = Flask(__name__)
cors = CORS(app, resources={r"/api/*": {"origins": "*"}})
50
Mathieu Rodic

After_requestフックを使用できます:

 @ app.after_request 
 def after_request(response):
 response.headers.add( 'Access-Control-Allow-Origin'、 '*')
 response.headers.add( 'Access-Control-Allow-Headers'、 'C​​ontent-Type、Authorization')
 response.headers.add( 'Access-Control-Allow-Methods'、 'GET、PUT、 POST、DELETE ')
 return response 

詳細については、このチュートリアルを確認してください- http://tutsbucket.com/tutorials/building-a-blog-using-flask-and-angularjs-part-1/

20
John Kenn

ブラウザーの実際のリクエストの前に毎回呼び出されるOPTIONSメソッドです。 OPTIONS応答では、メソッドとヘッダーが許可されています。 Flask OPTIONSリクエストを自動的に処理します。

クロスドメインリクエストにアクセスするには、APIにAccess-Control-Allow-Originヘッダーが必要です。特定のドメインを含めることができますが、任意のドメインからのリクエストを許可する場合は、Access-Control-Allow-Origin: *に設定できます。

flaskにCORSを設定するには、1つの拡張コードを見るか、この拡張機能を使用してみてください: https://github.com/wcdolphin/flask-cors/blob/master/flask_cors.py

flask-restfulのCORSを設定するには、このプルリクエストをご覧ください。 https://github.com/twilio/flask-restful/pull/122 および https:// github。 com/twilio/flask-restful/pull/131 。しかし、flask-restfulはデフォルトではまだサポートしていません。

4
tbicr

このコメントの更新です。 Flask CORSを使用する方法がありますが、flask.ext.corsは非推奨です。

つかいます: from flask_cors import CORS

3
Eric

この回避策はどうですか:

_from flask import Flask
from flask.ext import restful
from flask.ext.restful import Api
from flask.ext.sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config.from_object('config')

#flask-sqlalchemy
db = SQLAlchemy(app)

#flask-restful
api = restful.Api(app)

@app.after_request

def after_request(response):
  response.headers.add('Access-Control-Allow-Origin', '*')
  response.headers.add('Access-Control-Allow-Headers', 'Content-Type,Authorization')
  response.headers.add('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE')
  return response

import views
_

これは this チュートリアルから取りました。とても良い作品です。実際、これはこれまで見てきた中で最高のアプローチだと思います。

各エンドポイントで_{'Access-Control-Allow-Origin': '*'}_を返すことは、すべてのエンドポイントで追加する必要があるため、効率的ではないようです。少々イライラする...、少なくとも私にとっては。

@cors.crossdomain(Origin='*')を試しましたが、[〜#〜] get [〜#〜]リクエストでのみ動作するようです。

2

WebサービスAPIでリモートCORSリクエストを許可するには、次のようにflask restful APIを初期化するだけです。

from flask import Flask
from flask_restful import reqparse, abort, Api, Resource
from flask_cors import CORS

app = Flask(__name__)
cors = CORS(app, resources={r"*": {"origins": "*"}})
api = Api(app)

これにより、APIインスタンスにCORSヘッダーが追加され、すべてのOriginからのすべてのパスでCORSリクエストが許可されます。

0
domih

装飾を使って解決するのが好きです。

def cross_Origin(origin="*"):
    def cross_Origin(func):
        @functools.wraps(func)
        def _decoration(*args, **kwargs):
            ret = func(*args, **kwargs)
            _cross_Origin_header = {"Access-Control-Allow-Origin": Origin,
                                    "Access-Control-Allow-Headers":
                                        "Origin, X-Requested-With, Content-Type, Accept"}
            if isinstance(ret, Tuple):
                if len(ret) == 2 and isinstance(ret[0], dict) and isinstance(ret[1], int):
                    # this is for handle response like: ```{'status': 1, "data":"ok"}, 200```
                    return ret[0], ret[1], _cross_Origin_header
                Elif isinstance(ret, basestring):
                    response = make_response(ret)
                    response.headers["Access-Control-Allow-Origin"] = Origin
                    response.headers["Access-Control-Allow-Headers"] = "Origin, X-Requested-With, Content-Type, Accept"
                    return response
                Elif isinstance(ret, Response):
                    ret.headers["Access-Control-Allow-Origin"] = Origin
                    ret.headers["Access-Control-Allow-Headers"] = "Origin, X-Requested-With, Content-Type, Accept"
                    return ret
                else:
                    raise ValueError("Cannot handle cross Origin, because the return value is not matched!")
            return ret

        return _decoration

    return cross_Origin

そして、安らかなAPIで装飾を使用します。

class ExampleRestfulApi(Resource)
    @cross_Origin()
    def get(self):
        # allow all cross domain access
        pass

    @cross_Origin(origin="192.168.1.100")
    def post(self):
        # allow 192.168.1.100 access
        pass
0
gordonpro