web-dev-qa-db-ja.com

Javascript-要求されたリソースに「Access-Control-Allow-Origin」ヘッダーがありません

JavaScriptからXmlHttpRequestを介してPythonサーバーにデータを送信する必要があります。localhostを使用しているため、 [〜# 〜] cors [〜#〜] 。Flaskフレームワークとそのモジュールflask_cors

JavaScriptとして私はこれを持っています:

    var xmlhttp;
    if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari
        xmlhttp = new XMLHttpRequest();
    }
    else {// code for IE6, IE5
        xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
    }
    xmlhttp.open("POST", "http://localhost:5000/signin", true);
    var params = "email=" + email + "&password=" + password;


    xmlhttp.onreadystatechange = function() {//Call a function when the state changes.
        if(xmlhttp.readyState == 4 && xmlhttp.status == 200) {
            alert(xmlhttp.responseText);
        }
    }
    xmlhttp.send(params);

およびPythonコード:

@app.route('/signin', methods=['POST'])
@cross_Origin()
def sign_in():
    email = cgi.escape(request.values["email"])
    password = cgi.escape(request.values["password"])

しかし、実行すると次のメッセージが表示されます。

XMLHttpRequestはlocalhost:5000/signinをロードできません。要求されたリソースに「Access-Control-Allow-Origin」ヘッダーがありません。したがって、Origin 'null'はアクセスを許可されません。

どうすれば修正できますか? 「Access-Control-Allow-Origin」ヘッダーを使用する必要があることは知っていますが、このコードでそれを実装する方法がわかりません。ところで、純粋なJavaScriptを使用する必要があります。

45

JavascriptがFlaskで動作するようにしました。これは decorator を使用し、受け入れ可能なメソッドのリストに「OPTIONS」を追加します。この:

@app.route('/login', methods=['POST', 'OPTIONS'])
@crossdomain(Origin='*')
def login()
    ...

編集:リンクが壊れているようです。これが私が使ったデコレーターです。

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

def crossdomain(Origin=None, methods=None, headers=None, max_age=21600,
                attach_to_all=True, automatic_options=True):
    """Decorator function that allows crossdomain requests.
      Courtesy of
      https://blog.skyred.fi/articles/better-crossdomain-snippet-for-flask.html
    """
    if methods is not None:
        methods = ', '.join(sorted(x.upper() for x in methods))
    # use str instead of basestring if using Python 3.x
    if headers is not None and not isinstance(headers, basestring):
        headers = ', '.join(x.upper() for x in headers)
    # use str instead of basestring if using Python 3.x
    if not isinstance(Origin, basestring):
        Origin = ', '.join(Origin)
    if isinstance(max_age, timedelta):
        max_age = max_age.total_seconds()

    def get_methods():
        """ Determines which methods are allowed
        """
        if methods is not None:
            return methods

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

    def decorator(f):
        """The decorator function
        """
        def wrapped_function(*args, **kwargs):
            """Caries out the actual cross domain code
            """
            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)
            h['Access-Control-Allow-Credentials'] = 'true'
            h['Access-Control-Allow-Headers'] = \
                "Origin, X-Requested-With, Content-Type, Accept, Authorization"
            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
32
Zachary Jacobi

flask-cors拡張機能を使用しました。

pip install flask-corsを使用してインストールする

それから単純に

from flask_cors import CORS
app = Flask(__name__)
CORS(app)

これにより、すべてのドメインが許可されます

70
campervancoder

古い質問ですが、この問題を抱える今後のグーグルのために、app.pyファイルに次を追加することで、フラスコレスフルアプリの問題(およびCORSに関連する他のいくつかのダウンストリームの問題)を解決しました:

app = Flask(__name__)
api = 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,OPTIONS')
  return response


if __== '__main__':
    app.run()
43
Luc Gendrot

python 2.7を使用する場合

app = Flask(__name__)
api = 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,OPTIONS')
  return response


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

Python3以降で実行する場合は、pip install flask-corsコマンドを使用してFlask-corsをインストールします。次を追加します。

from flask_cors import CORS
app = Flask(__name__)
CORS(app)
18
Alok Patra

実際にFlaskサイトにAccess-Control-Allow-Originヘッダーサーバー側を変更するためのすばらしいスニペットがあります。 http://flask.pocoo.org/snippets/56/

そこから簡単な方法があります。つまり、すべての*ドメインがURLにアクセスできるようにするか、ヘッダー内で選択したURLを指定します。

CORSに関するMDNの記事 から:

この場合、サーバーはAccess-Control-Allow-Origin: *で応答します。これは、リソースがクロスサイト方式で任意のドメインからアクセスできることを意味します。 http://bar.other のリソース所有者が、リソースへのアクセスを http://foo.example からのみに制限したい場合、彼らは送り返します: Access-Control-Allow-Origin: http://foo.example

6
boxmein

Zacharyのソリューションを使用しました。うまくいく。

新しいデコレータをどこに置くべきか疑問に思っている人のために:

Zacharyが提供したリンクからコードをコピーして、.pyファイル

pythonモジュールが存在するフォルダーに配置します(使用するシステムと仮想環境を使用しているかどうかによって異なります)。

flaskアプリで、新しく作成したpythonモジュールからcrossdomainメソッドをインポートして使用します。

2
Vikas

Access-Control-Allow-Originは、ユーザーではなくサーバーによって送信される必要があります。別のドメインを呼び出すと、ブラウザはこのヘッダーがサーバーから返されるかどうかを確認します。そうでない場合、呼び出しは失敗します。私はPythonを知らないので、サーバーにこのヘッダーを送信させる方法がわかりません。

0
Oscar Paz