我开发了一个带有Flask Restful的小型只写REST api,它接受来自少数可能有更改IP地址的客户端的PUT请求。我的客户是运行AngularJS前端的嵌入式Chromium客户端;他们使用简单的魔法密钥对我的API进行身份验证 - 这对我的规模非常有限。
我正在测试部署我的API,我注意到Angular客户端正在尝试向我的Flask服务发送OPTIONS http方法。我的API同时回复了404(因为我还没有编写OPTIONS处理程序,只有PUT处理程序)。似乎在发送非POST或GET的跨域请求时,Angular将在服务器上发送一个pre-flight OPTIONS方法,以确保在发送实际请求之前接受跨域请求。是吗?
无论如何,我如何允许所有跨域PUT请求到Flask Restful API?我之前使用了带有(非宁静的)Flask实例的cross-domaion装饰器,但是我是否需要在我的API中编写OPTIONS处理程序?
答案 0 :(得分:45)
使用Flask-CORS模块,您可以在不更改代码的情况下执行跨域请求 。
from flask.ext.cors import CORS
app = Flask(__name__)
cors = CORS(app, resources={r"/api/*": {"origins": "*"}})
根据Eric建议, flask.ext.cors
模块现已弃用,您应该使用以下代码:
from flask_cors import CORS
app = Flask(__name__)
cors = CORS(app, resources={r"/api/*": {"origins": "*"}})
答案 1 :(得分:19)
您可以使用after_request钩子:
@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') return response
查看本教程以获取更多详细信息 - http://tutsbucket.com/tutorials/building-a-blog-using-flask-and-angularjs-part-1/
答案 2 :(得分:18)
我通过重写我的Flask后端解决了这个问题,以便在我的PUT响应中使用Access-Control-Allow-Origin标头进行回答。此外,我在Flask应用程序中创建了一个OPTIONS处理程序,通过遵循我在http RFC中读到的内容来回答options方法。
PUT方法的返回如下所示:
return restful.request.form, 201, {'Access-Control-Allow-Origin': '*'}
My OPTIONS方法处理程序如下所示:
def options (self):
return {'Allow' : 'PUT' }, 200, \
{ 'Access-Control-Allow-Origin': '*', \
'Access-Control-Allow-Methods' : 'PUT,GET' }
@tbicr是对的:Flask会自动为你回答OPTIONS方法。但是,在我的情况下,它没有传输具有该答案的Access-Control-Allow-Origin标头,因此我的浏览器从api获得了回复,这似乎意味着不允许跨域请求。我在我的情况下重载了选项请求,并添加了ACAO标题,浏览器似乎对此感到满意,并使用PUT跟进了OPTIONS。
答案 3 :(得分:4)
你是对的,OPTIONS
方法每次在浏览器中的实际请求之前调用。 OPTIONS
响应已允许方法和标头。 Flask自动处理OPTIONS
个请求。
要获取跨域请求的访问权限,您的API必须具有Access-Control-Allow-Origin
标头。它可以包含特定域,但如果您希望来自任何域的允许请求,则可以将其设置为Access-Control-Allow-Origin: *
。
要为flask
设置CORS,您可以查看一个扩展程序代码或尝试使用此扩展程序:https://github.com/wcdolphin/flask-cors/blob/master/flask_cors.py。
要为flask-restful
设置CORS,请查看此拉取请求:https://github.com/twilio/flask-restful/pull/122和https://github.com/twilio/flask-restful/pull/131。但看起来flask-restful
默认情况下不支持它。
答案 4 :(得分:3)
只是对此评论的更新。 Flask CORS是可行的方法,但不推荐使用flask.ext.cors。
使用:
from flask_cors import CORS
答案 5 :(得分:2)
这个解决方法怎么样:
from flask import Flask
from flask.ext import restful
from flask.ext.restful import Api
from flask.ext.sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config.from_object('config')
#flask-sqlalchemy
db = SQLAlchemy(app)
#flask-restful
api = restful.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')
return response
import views
我是从this教程中学到的。效果很好。实际上,我认为这是迄今为止我见过的最佳方法。
在每个端点上返回{'Access-Control-Allow-Origin': '*'}
似乎没有效率,因为您必须在每个端点上添加它。有点恼人......至少对我而言。
我尝试了@cors.crossdomain(origin='*')
,但看起来它只适用于 GET 请求。
答案 6 :(得分:0)
我喜欢用装饰来解决。
def cross_origin(origin="*"):
def cross_origin(func):
@functools.wraps(func)
def _decoration(*args, **kwargs):
ret = func(*args, **kwargs)
_cross_origin_header = {"Access-Control-Allow-Origin": origin,
"Access-Control-Allow-Headers":
"Origin, X-Requested-With, Content-Type, Accept"}
if isinstance(ret, tuple):
if len(ret) == 2 and isinstance(ret[0], dict) and isinstance(ret[1], int):
# this is for handle response like: ```{'status': 1, "data":"ok"}, 200```
return ret[0], ret[1], _cross_origin_header
elif isinstance(ret, basestring):
response = make_response(ret)
response.headers["Access-Control-Allow-Origin"] = origin
response.headers["Access-Control-Allow-Headers"] = "Origin, X-Requested-With, Content-Type, Accept"
return response
elif isinstance(ret, Response):
ret.headers["Access-Control-Allow-Origin"] = origin
ret.headers["Access-Control-Allow-Headers"] = "Origin, X-Requested-With, Content-Type, Accept"
return ret
else:
raise ValueError("Cannot handle cross origin, because the return value is not matched!")
return ret
return _decoration
return cross_origin
然后,在宁静的api中使用装饰。
class ExampleRestfulApi(Resource)
@cross_origin()
def get(self):
# allow all cross domain access
pass
@cross_origin(origin="192.168.1.100")
def post(self):
# allow 192.168.1.100 access
pass
答案 7 :(得分:0)
要在您的Web服务api上允许远程CORS请求,您可以像这样简单地初始化flask restful API:
from flask import Flask
from flask_restful import reqparse, abort, Api, Resource
from flask_cors import CORS
app = Flask(__name__)
cors = CORS(app, resources={r"*": {"origins": "*"}})
api = Api(app)
这会将CORS标头添加到您的api实例,并允许来自每个起点的每个路径上的CORS请求。
答案 8 :(得分:0)
我从角度连接到我的烧瓶休息API时遇到了多种类型的CORS问题,并尝试了几乎所有方法。
如果您希望不受限制地访问所有网站,则可以在app.py
脚本中添加以下代码:
from flask_cors import CORS , cross_origin
cors = CORS(app, resources={r"/*": {"origins": "*"}})
这可以工作,但是建议您具有一定的安全性,您可以随时在原始位置进行编辑