我正在尝试使用jquery创建一个交叉原始请求,但它一直被消息拒绝
XMLHttpRequest无法加载http:// ... No' Access-Control-Allow-Origin' 标头出现在请求的资源上。起源......因此 不允许访问。
我正在使用flask,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方面,我正在使用烧瓶,就像这样
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 __name__ == '__main__':
app.run()
答案 0 :(得分:64)
当我部署到Heroku时,这对我有用。
http://flask-cors.readthedocs.org/en/latest/
通过运行安装烧瓶 -
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!"
答案 1 :(得分:20)
好的,我不认为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
这就是全部~~
答案 2 :(得分:3)
我刚刚遇到了同样的问题,我开始相信其他答案比他们需要的要复杂一些,因此对于那些不想依赖更多库或装饰器的人来说,这是我的方法:
CORS请求实际上包含两个HTTP请求。预检请求,然后只有在预检成功通过后才发出的实际请求。
在实际的跨域POST
请求之前,浏览器将发出OPTIONS
请求。此响应不应返回任何正文,而应仅返回一些令人放心的标头,告诉标头浏览器可以执行此跨域请求,并且不属于某些跨站点脚本攻击的一部分。
我编写了一个Python函数,用于使用make_response
模块中的flask
函数来构建此响应。
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标头-否则浏览器不会将响应返回给调用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
答案 3 :(得分:2)
尝试以下装饰器:
@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 __name__ == '__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
答案 4 :(得分:2)
上面的所有响应都可以,但是您仍然可能会收到CORS错误,例如,如果应用程序抛出了您未处理的错误(例如键错误),并且您没有正确进行输入验证,例如。您可以添加错误处理程序以捕获所有异常实例,并在服务器响应中添加CORS响应标头
因此,定义一个错误处理程序-errors.py:
from flask import json, make_response, jsonify
from werkzeug.exceptions import HTTPException
# define an error handling function
def init_handler(app):
# catch every type of exception
@app.errorhandler(Exception)
def handle_exception(e):
#loggit()!
# return json response of error
if isinstance(e, HTTPException):
response = e.get_response()
# replace the body with JSON
response.data = json.dumps({
"code": e.code,
"name": e.name,
"description": e.description,
})
else:
# build response
response = make_response(jsonify({"message": 'Something went wrong'}), 500)
# add the CORS header
response.headers['Access-Control-Allow-Origin'] = '*'
response.content_type = "application/json"
return response
然后使用Billal's答案:
from flask import Flask
from flask_cors import CORS
# import error handling file from where you have defined it
from . import errors
app = Flask(__name__)
CORS(app) # This will enable CORS for all routes
errors.init_handler(app) # initialise error handling
答案 5 :(得分:2)
改进此处描述的解决方案:https://stackoverflow.com/a/52875875/10299604
使用after_request
,我们可以处理CORS响应标头,而无需向端点添加额外的代码:
### CORS section
@app.after_request
def after_request_func(response):
origin = request.headers.get('Origin')
if request.method == 'OPTIONS':
response = make_response()
response.headers.add('Access-Control-Allow-Credentials', 'true')
response.headers.add('Access-Control-Allow-Headers', 'Content-Type')
response.headers.add('Access-Control-Allow-Headers', 'x-csrf-token')
response.headers.add('Access-Control-Allow-Methods',
'GET, POST, OPTIONS, PUT, PATCH, DELETE')
if origin:
response.headers.add('Access-Control-Allow-Origin', origin)
else:
response.headers.add('Access-Control-Allow-Credentials', 'true')
if origin:
response.headers.add('Access-Control-Allow-Origin', origin)
return response
### end CORS section
答案 6 :(得分:1)
如果要为所有路由启用CORS,则只需安装flask_cors扩展名(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无关。 / p>
答案 7 :(得分:1)
我使用flask和此库在python中解决了相同的问题。 flask_cors
答案 8 :(得分:0)
我的解决方案是围绕app.route进行包装:
Theme basicTheme;
Button close;
Panel panel;
void settings() {
size(400, 600, P2D);
}
void setup() {
basicTheme = new Theme();
close = new Button();
close.setBounds(10, 10, 100, 25);
close.setText("close");
panel = new Panel();
panel.setBounds(50, 200, 200, 200);
panel.add(close);
}
void draw() {
background(255);
basicTheme.display(panel);
}
答案 9 :(得分:0)
围绕app.route的包装效果最好
Microsoft.EntityFrameworkCore.Design
答案 10 :(得分:0)
如果找不到问题,并且代码可以正常工作,则可能是您的请求即将达到heroku允许您提出请求的最大时间。如果用时超过30秒,Heroku将取消请求。
答案 11 :(得分:0)
我可以通过添加来处理 cors
from flask_cors import CORS, cross_origin
app = Flask(__name__)
cors = CORS(app)
app.config['CORS_HEADERS'] = 'Content-Type'
@cross_origin()