Jqueryを使用してクロスオリジンリクエストを作成しようとしていますが、メッセージで拒否され続けます
XMLHttpRequestがhttp://をロードできません...要求されたリソースに「Access-Control-Allow-Origin」ヘッダーがありません。したがって、Origin ...はアクセスを許可されません。
フラスコ、heroku、jqueryを使用しています
クライアントコードは次のようになります。
$(document).ready(function() {
$('#submit_contact').click(function(e){
e.preventDefault();
$.ajax({
type: 'POST',
url: 'http://...',
// data: [
// { name: "name", value: $('name').val()},
// { name: "email", value: $('email').val() },
// { name: "phone", value: $('phone').val()},
// { name: "description", value: $('desc').val()}
//
// ],
data:"name=3&email=3&phone=3&description=3",
crossDomain:true,
success: function(msg) {
alert(msg);
}
});
});
});
heroku側ではflaskを使用しています。これは次のようなものです
from flask import Flask,request
from flask.ext.mandrill import Mandrill
try:
from flask.ext.cors import CORS # The typical way to import flask-cors
except ImportError:
# Path hack allows examples to be run without installation.
import os
parentdir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
os.sys.path.insert(0, parentdir)
from flask.ext.cors import CORS
app = Flask(__name__)
app.config['MANDRILL_API_KEY'] = '...'
app.config['MANDRILL_DEFAULT_FROM']= '...'
app.config['QOLD_SUPPORT_EMAIL']='...'
app.config['CORS_HEADERS'] = 'Content-Type'
mandrill = Mandrill(app)
cors = CORS(app)
@app.route('/email/',methods=['POST'])
def hello_world():
name=request.form['name']
email=request.form['email']
phone=request.form['phone']
description=request.form['description']
mandrill.send_email(
from_email=email,
from_name=name,
to=[{'email': app.config['QOLD_SUPPORT_EMAIL']}],
text="Phone="+phone+"\n\n"+description
)
return '200 OK'
if __== '__main__':
app.run()
これがHerokuにデプロイしたときに私にとってうまくいったことです。
http://flask-cors.readthedocs.org/en/latest/
実行してフラスコ-corsをインストールします-pip install -U flask-cors
from flask import Flask
from flask_cors import CORS, cross_Origin
app = Flask(__name__)
cors = CORS(app)
app.config['CORS_HEADERS'] = 'Content-Type'
@app.route("/")
@cross_Origin()
def helloWorld():
return "Hello, cross-Origin-world!"
OK、galuszkakによって言及された公式スニペットがどこでも使用されるべきではないと思います。hello_world
関数。応答が正しいか正しくないかにかかわらず、Access-Control-Allow-Origin
ヘッダーは、私たちが懸念すべきものです。だから、次のように物事は非常に簡単です。
@blueprint.after_request # blueprint can also be app~~
def after_request(response):
header = response.headers
header['Access-Control-Allow-Origin'] = '*'
return response
以上です~~
私はちょうど同じ問題に直面しており、他の答えは必要以上に複雑であると信じるようになりました。そこで、これ以上のライブラリやデコレータに依存したくない人のための私のアプローチを以下に示します。
CORSリクエストは、実際には2つのHTTPリクエストで構成されています。プリフライトリクエストと、プリフライトが正常に通過した場合にのみ行われる実際のリクエスト。
実際のクロスドメインPOST
リクエストの前に、ブラウザはOPTIONS
リクエストを発行します。この応答は本文を返すべきではありませんが、このクロスドメインリクエストを行うことは問題なく、クロスサイトスクリプティング攻撃の一部ではないことをブラウザに伝えるいくつかの安心できるヘッダーのみを返します。
flask
モジュールのmake_response
関数を使用してこの応答を作成するPython関数を作成しました。
def _build_cors_prelight_response():
response = make_response()
response.headers.add("Access-Control-Allow-Origin", "*")
response.headers.add("Access-Control-Allow-Headers", "*")
response.headers.add("Access-Control-Allow-Methods", "*")
return response
このレスポンスは、すべてのリクエストに対して機能するワイルドカードです。 CORSによって得られる追加のセキュリティが必要な場合は、オリジン、ヘッダー、およびメソッドのホワイトリストを提供する必要があります。
この応答は、(Chrome)ブラウザーに実際の要求を行うよう説得します。
実際のリクエストを処理する場合、CORSヘッダーを1つ追加する必要があります-それ以外の場合、ブラウザーは呼び出し元のJavaScriptコードに応答を返しません。代わりに、クライアント側でリクエストが失敗します。 jsonifyを使用した例
response = jsonify({"order_id": 123, "status": "shipped"}
response.headers.add("Access-Control-Allow-Origin", "*")
return response
そのための関数も作成しました。
def _corsify_actual_response(response):
response.headers.add("Access-Control-Allow-Origin", "*")
return response
ワンライナーを返すことができます。
from flask import Flask, request, jsonify, make_response
from models import OrderModel
flask_app = Flask(__name__)
@flask_app.route("/api/orders", methods=["POST", "OPTIONS"])
def api_create_order():
if request.method == "OPTIONS": # CORS preflight
return _build_cors_prelight_response()
Elif request.method == "POST": # The actual request following the preflight
order = OrderModel.create(...) # Whatever.
return _corsify_actual_response(jsonify(order.to_dict()))
else
raise RuntimeError("Wierd - don't know how to handle method {}".format(request.method))
def _build_cors_prelight_response():
response = make_response()
response.headers.add("Access-Control-Allow-Origin", "*")
response.headers.add('Access-Control-Allow-Headers', "*")
response.headers.add('Access-Control-Allow-Methods', "*")
return response
def _corsify_actual_response(response):
response.headers.add("Access-Control-Allow-Origin", "*")
return response
すべてのルートでCORSを有効にする場合は、 flask_cors extension(_pip3 install -U flask_cors
_)をインストールして、app
を次のようにラップします:CORS(app)
。
それで十分です(画像をアップロードするPOST
リクエストでこれをテストしましたが、うまくいきました):
_from flask import Flask
from flask_cors import CORS
app = Flask(__name__)
CORS(app) # This will enable CORS for all routes
_
重要な注意:ルートにエラーがある場合、存在しない変数を出力しようとすると、実際にはCORSとは関係のないCORSエラー関連のメッセージが表示されます。
次のデコレータを試してください。
@app.route('/email/',methods=['POST', 'OPTIONS']) #Added 'Options'
@crossdomain(Origin='*') #Added
def hello_world():
name=request.form['name']
email=request.form['email']
phone=request.form['phone']
description=request.form['description']
mandrill.send_email(
from_email=email,
from_name=name,
to=[{'email': app.config['QOLD_SUPPORT_EMAIL']}],
text="Phone="+phone+"\n\n"+description
)
return '200 OK'
if __== '__main__':
app.run()
このデコレータは次のように作成されます。
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):
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
このパッケージを確認することもできます Flask-CORS
私のソリューションはapp.routeのラッパーです:
def corsapp_route(path, Origin=('127.0.0.1',), **options):
"""
Flask app alias with cors
:return:
"""
def inner(func):
def wrapper(*args, **kwargs):
if request.method == 'OPTIONS':
response = make_response()
response.headers.add("Access-Control-Allow-Origin", ', '.join(Origin))
response.headers.add('Access-Control-Allow-Headers', ', '.join(Origin))
response.headers.add('Access-Control-Allow-Methods', ', '.join(Origin))
return response
else:
result = func(*args, **kwargs)
if 'Access-Control-Allow-Origin' not in result.headers:
result.headers.add("Access-Control-Allow-Origin", ', '.join(Origin))
return result
wrapper.__= func.__name__
if 'methods' in options:
if 'OPTIONS' in options['methods']:
return app.route(path, **options)(wrapper)
else:
options['methods'].append('OPTIONS')
return app.route(path, **options)(wrapper)
return wrapper
return inner
@corsapp_route('/', methods=['POST'], Origin=['*'])
def hello_world():
...