Javascript - No 'Access-Control-Allow-Origin' header is present on the requested resource
我需要通过
作为JavaScript我有这个:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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代码:
1 2 3 4 5 | @app.route('/signin', methods=['POST']) @cross_origin() def sign_in(): email = cgi.escape(request.values["email"]) password = cgi.escape(request.values["password"]) |
但是当我执行它时,我得到了这样的信息:
XMLHttpRequest cannot load localhost:5000/signin. No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'null' is therefore not allowed access.
我该如何解决? 我知道我需要使用一些"Access-Control-Allow-Origin"标头,但我不知道如何在此代码中实现它。 顺便说一下,我需要使用纯JavaScript。
我使用了烧瓶扩展。
使用
那就简单了
1 2 3 | from flask_cors import CORS app = Flask(__name__) CORS(app) |
这将允许所有域
老问题,但是对于有这个问题的未来googlers,我通过将以下内容添加到我的app.py文件中来解决它(以及与CORS有关的一些其他下游问题)
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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 __name__ == '__main__': app.run() |
我使用这个装饰器让Javascript与Flask一起工作,并在我可接受的方法列表中添加"OPTIONS"。应该在路径装饰器下面使用装饰器,如下所示:
1 2 3 4 | @app.route('/login', methods=['POST', 'OPTIONS']) @crossdomain(origin='*') def login() ... |
编辑:
链接似乎被打破了。这是我用的装饰器。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | 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 |
使用python 2.7时
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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 __name__ == '__main__': app.run() |
在python3或者前面运行时,
使用命令
添加以下内容:
1 2 3 | from flask_cors import CORS app = Flask(__name__) CORS(app) |
Flask网站上实际上有一个很棒的片段来修改
您可以轻松地从那里开始,即允许每个
来自MDN关于CORS的文章:
In this case, the server responds with a
Access-Control-Allow-Origin: * which means that the
resource can be accessed by any domain in a cross-site manner. If the resource owners at
http://bar.other wished to restrict access to the resource to be only from
http://foo.example, they would send back:
Access-Control-Allow-Origin: http://foo.example .
我使用了Zachary的解决方案。效果很好。
对于那些想知道放置新装饰器的人:
只需从Zachary提供的链接中复制代码并将其放在
将它放在python模块所在的文件夹中(根据您使用的系统以及您是否使用虚拟环境而有所不同)。
在您的烧瓶应用程序中,从新创建的python模块导入方法
Access-Control-Allow-Origin必须由服务器发送,而不是由您发送。当您调用另一个域时,浏览器会检查服务器是否返回此标头。如果不是,则呼叫失败。我不知道Python,所以我不知道如何让你的服务器发送这个标题,或者即使你可以修改服务器。