Python 用 Flask 解决跨域资源共享
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/26980713/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Solve Cross Origin Resource Sharing with Flask
提问by Matteo
For the following ajaxpost request for Flask(how can I use data posted from ajax in flask?):
对于以下ajax发布请求Flask(如何使用从 ajax 在 Flask 中发布的数据?):
$.ajax({
url: "http://127.0.0.1:5000/foo",
type: "POST",
contentType: "application/json",
data: JSON.stringify({'inputVar': 1}),
success: function( data ) {
alert( "success" + data );
}
});
I get a Cross Origin Resource Sharing (CORS)error:
我收到一个Cross Origin Resource Sharing (CORS)错误:
No 'Access-Control-Allow-Origin' header is present on the requested resource.
Origin 'null' is therefore not allowed access.
The response had HTTP status code 500.
I tried solving it in the two following ways, but none seems to work.
我尝试通过以下两种方式解决它,但似乎都不起作用。
- Using Flask-CORS
- 使用 Flask-CORS
This is a Flaskextension for handling CORSthat should make cross-origin AJAX possible.
这是一个Flask处理扩展CORS,应该使跨域 AJAX 成为可能。
- http://flask-cors.readthedocs.org/en/latest/
- How to enable CORS in flask and heroku
- Flask-cors wrapper not working when jwt auth wrapper is applied.
- Javascript - No 'Access-Control-Allow-Origin' header is present on the requested resource
- http://flask-cors.readthedocs.org/en/latest/
- 如何在flask和heroku中启用CORS
- 应用 jwt auth 包装器时,Flask-cors 包装器不起作用。
- Javascript - 请求的资源上不存在“Access-Control-Allow-Origin”标头
My pythonServer.pyusing this solution:
我的pythonServer.py使用这个解决方案:
from flask import Flask
from flask.ext.cors import CORS, cross_origin
app = Flask(__name__)
cors = CORS(app, resources={r"/foo": {"origins": "*"}})
app.config['CORS_HEADERS'] = 'Content-Type'
@app.route('/foo', methods=['POST','OPTIONS'])
@cross_origin(origin='*',headers=['Content-Type','Authorization'])
def foo():
return request.json['inputVar']
if __name__ == '__main__':
app.run()
- Using specific Flask Decorator
- 使用特定的 Flask 装饰器
This is an officialFlask code snippet defining a decorator that should allow CORSon the functions it decorates.
这是一个官方的Flask 代码片段,定义了一个装饰器,它应该允许CORS它装饰的函数。
- http://flask.pocoo.org/snippets/56/
- Python Flask cross site HTTP POST - doesn't work for specific allowed origins
- http://chopapp.com/#351l7gc3
- http://flask.pocoo.org/snippets/56/
- Python Flask 跨站点 HTTP POST - 不适用于特定的允许来源
- http://chopapp.com/#351l7gc3
My pythonServer.pyusing this solution:
我的pythonServer.py使用这个解决方案:
from flask import Flask, make_response, request, current_app
from datetime import timedelta
from functools import update_wrapper
app = Flask(__name__)
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
@app.route('/foo', methods=['GET','POST','OPTIONS'])
@crossdomain(origin="*")
def foo():
return request.json['inputVar']
if __name__ == '__main__':
app.run()
Can you please give some some indication of why that is?
你能给出一些说明为什么会这样吗?
采纳答案by Satish
It worked like a champ, after bit modification to your code
在对您的代码进行一些修改后,它就像一个冠军
# initialization
app = Flask(__name__)
app.config['SECRET_KEY'] = 'the quick brown fox jumps over the lazy dog'
app.config['CORS_HEADERS'] = 'Content-Type'
cors = CORS(app, resources={r"/foo": {"origins": "http://localhost:port"}})
@app.route('/foo', methods=['POST'])
@cross_origin(origin='localhost',headers=['Content- Type','Authorization'])
def foo():
return request.json['inputVar']
if __name__ == '__main__':
app.run()
I replaced * by localhost. Since as I read in many blogs and posts, you should allow access for specific domain
我用 localhost 替换了 *。正如我在许多博客和帖子中所读到的那样,您应该允许访问特定域
回答by Per Kristian
I struggled a lot with something similar. Try the following:
我在类似的事情上挣扎了很多。请尝试以下操作:
- Use some sort of browser plugin which can display the HTML headers.
- Enter the URL to your service, and view the returned header values.
- Make sure Access-Control-Allow-Origin is set to one and only one domain, which should be the request origin. Do not set Access-Control-Allow-Origin to *.
- 使用某种可以显示 HTML 标题的浏览器插件。
- 输入您的服务的 URL,并查看返回的标头值。
- 确保 Access-Control-Allow-Origin 设置为一个且只有一个域,该域应该是请求源。不要将 Access-Control-Allow-Origin 设置为 *。
If this doesn't help, take a look at this article. It's on PHP, but it describes exactly which headers must be set to which values for CORS to work.
如果这没有帮助,请查看这篇文章。它在 PHP 上,但它准确地描述了必须将哪些标头设置为哪些值才能使 CORS 工作。
回答by Jaza
Note that setting the Access-Control-Allow-Originheader in the Flask response object is fine in many cases (such as this one), but it has no effect when serving static assets (in a production setup, at least). That's because static assets are served directly by the front-facing web server (usually Nginx or Apache). So, in that case, you have to set the response header at the web server level, not in Flask.
请注意,Access-Control-Allow-Origin在许多情况下(例如这个),在 Flask 响应对象中设置标头是没问题的,但在提供静态资产时(至少在生产设置中)没有任何影响。这是因为静态资产直接由前端 Web 服务器(通常是 Nginx 或 Apache)提供服务。因此,在这种情况下,您必须在 Web 服务器级别而不是在 Flask 中设置响应标头。
For more details, see this article that I wrote a while back, explaining how to set the headers(in my case, I was trying to do cross-domain serving of Font Awesome assets).
有关更多详细信息,请参阅我不久前写的这篇文章,其中解释了如何设置标题(在我的例子中,我试图对 Font Awesome 资产进行跨域服务)。
Also, as @Satu said, you may need to allow access only for a specific domain, in the case of JS AJAX requests. For requesting static assets (like font files), I think the rules are less strict, and allowing access for any domain is more accepted.
此外,正如@Satu 所说,在 JS AJAX 请求的情况下,您可能只需要允许访问特定域。对于请求静态资产(如字体文件),我认为规则不那么严格,并且更容易接受允许访问任何域。
回答by Salvador Dali
You can get the results with a simple:
您可以通过简单的方式获得结果:
@app.route('your route', methods=['GET'])
def yourMethod(params):
response = flask.jsonify({'some': 'data'})
response.headers.add('Access-Control-Allow-Origin', '*')
return response
回答by Juha Untinen
Might as well make this an answer. I had the same issue today and it was more of a non-issue than expected. After adding the CORS functionality, you mustrestart your Flask server (ctrl + c-> python manage.py runserver, or whichever method you use)) in order for the change to take effect, even if the code is correct. Otherwise the CORS will not work in the active instance.
不妨把这个作为一个答案。我今天遇到了同样的问题,它比预期的更不是问题。添加 CORS 功能后,您必须重新启动 Flask 服务器(ctrl + c->python manage.py runserver或您使用的任何方法))以使更改生效,即使代码正确也是如此。否则 CORS 将无法在活动实例中工作。
Here's how it looks like for me and it works (Python 3.6.1, Flask 0.12):
这是我的样子和它的工作原理(Python 3.6.1,Flask 0.12):
factory.py:
工厂.py:
from flask import Flask
from flask_cors import CORS # This is the magic
def create_app(register_stuffs=True):
"""Configure the app and views"""
app = Flask(__name__)
CORS(app) # This makes the CORS feature cover all routes in the app
if register_stuffs:
register_views(app)
return app
def register_views(app):
"""Setup the base routes for various features."""
from backend.apps.api.views import ApiView
ApiView.register(app, route_base="/api/v1.0/")
views.py:
视图.py:
from flask import jsonify
from flask_classy import FlaskView, route
class ApiView(FlaskView):
@route("/", methods=["GET"])
def index(self):
return "API v1.0"
@route("/stuff", methods=["GET", "POST"])
def news(self):
return jsonify({
"stuff": "Here be stuff"
})
In my React app console.log:
在我的 React 应用程序 console.log 中:
Sending request:
GET /stuff
With parameters:
null
bundle.js:17316 Received data from Api:
{"stuff": "Here be stuff"}
回答by Nagashayan
Well, I faced the same issue. For new users who may land at this page. Just follow their official documentation.
好吧,我遇到了同样的问题。对于可能登陆此页面的新用户。只需按照他们的官方文档进行操作即可。
Install flask-cors
安装 Flask-cors
pip install -U flask-cors
then after app initialization, initialize flask-corswith default arguments:
然后在应用程序初始化后,flask-cors使用默认参数进行初始化:
from flask import Flask
from flask_cors import CORS
app = Flask(__name__)
CORS(app)
@app.route("/")
def helloWorld():
return "Hello, cross-origin-world!"
回答by D.Waasala
I used decorator given by Armin Ronacherwith little modifications (due to different headers that are requested by the client).And that worked for me. (where I use angular as the requester requesting application/json type).
我使用了 Armin Ronacher提供的装饰器,稍作修改(由于客户端请求的标头不同)。这对我有用。(我使用 angular 作为请求应用程序/json 类型的请求者)。
The code is slightly modified at below places,
代码在以下地方略有修改,
from flask import jsonify
@app.route('/my_service', methods=['POST', 'GET','OPTIONS'])
@crossdomain(origin='*',headers=['access-control-allow-origin','Content-Type'])
def my_service():
return jsonify(foo='cross domain ftw')
jsonify will send a application/json type, else it will be text/html. headers are added as the client in my case request for those headers
jsonify 将发送一个 application/json 类型,否则它将是 text/html。在我对这些标头的请求中,标头被添加为客户端
const httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json',
'Access-Control-Allow-Origin':'*'
})
};
return this.http.post<any>(url, item,httpOptions)
回答by Dila Gurung
Note: The placement of cross_origin should be right and dependencies are installed. On the client side, ensure to specify kind of data server is consuming. For example application/json or text/html
注意:cross_origin 的位置应该是对的,并且已经安装了依赖。在客户端,确保指定服务器正在消耗的数据类型。例如 application/json 或 text/html
For me the code written below did magic
对我来说,下面写的代码很神奇
from flask import Flask,request,jsonify
from flask_cors import CORS,cross_origin
app=Flask(__name__)
CORS(app, support_credentials=True)
@app.route('/api/test', methods=['POST', 'GET','OPTIONS'])
@cross_origin(supports_credentials=True)
def index():
if(request.method=='POST'):
some_json=request.get_json()
return jsonify({"key":some_json})
else:
return jsonify({"GET":"GET"})
if __name__=="__main__":
app.run(host='0.0.0.0', port=5000)

