Flask-RESTplus CORS 请求不将标头添加到响应中



我在尝试为我的 REST API 设置 CORS 时遇到问题。 我目前正在使用 Flask-Restplus 软件包。这是我的端点的样子:

@api_ns.route('/some/endpoint')
@api_ns.response(code=400, description='Bad Request.')
class AEndpointResource(Resource):
@api_ns.param(**api_req_fields.POST_DOC)
@api_ns.expect(POST_REQUIRED_BODY)
@api_ns.marshal_with(code=201,
fields=my_api_models.MyEndpointResponse.get_serializer(),
description=my_api_models.MyEndpointResponse.description)
def post(self) -> Tuple[my_api_models.MyEndpointResponse, int]:
"""
The post body
"""
# Some logic here
return response, 200

如果我编写一个小的 JavaScript 片段并尝试在浏览器中启动它,我会得到一个错误,因为没有 CORS 标头。我看到 Flask-Restplus 已经在处理 OPTIONS 请求,而我没有告诉他任何事情。(根据此链接,这是有道理的,提到从 Flask 0.6 开始,OPTIONS 请求是自动处理的(

我的问题是,即使我尝试使用以下命令装饰我的端点:

from flask-restplus import cors   # <--- Adding this import
...
class AnEndpointResource(Resource):
...
@my_other_decorators
...
@cors.crossdomain(origin='*')  # <--- Adding this new decorator on my endpoint
def post(self) -> Tuple[my_api_models.MyEndpointResponse, int]:
...

没有任何变化,我仍然得到与以前相同的结果。我从 OPTIONS 请求中获得了像以前一样自动处理的 HTTP 200,但我在响应中看不到我的新标头(即访问控制允许来源(。

我错过了什么吗?

使用 Flask-CORS,它可以工作:

from flask import Flask, request
from flask_restplus import Resource, Api, fields
from flask_cors import CORS
# configuration
DEBUG = True
# instantiate the app
app = Flask(__name__)
api = Api(app)
app.config.from_object(__name__)
# enable CORS
CORS(app, resources={r'/*': {'origins': '*'}})

在我的笔记本电脑和浏览器中进行本地测试时,我能够通过在响应中添加标头来解决 cors 问题。

之前:return state, 200

之后:return state, 200, {'Access-Control-Allow-Origin': '*'}

我测试过,您正在寻找的标头将添加到对后续GET请求的响应中。装饰器@cors.crossdomain有一个选项automatic_options默认情况下设置为True。这意味着您的 OPTIONS 请求仍将被自动处理。

请参阅此测试以检查它应该如何工作。

flask_restplus.cors模块没有记录,因此不确定是否应该使用它。

我也遇到了一个 CORS 问题,并以这种方式解决了它:

from flask import Flask
from flask_restplus import Api
app = Flask('name')
api = Api(app)
// your api code here

@app.after_request
def after_request(response):
response.headers.add('Access-Control-Allow-Origin', '*')
return response

问题是 flask-restplus 只将 CORS 标头分配给 GET 请求。当浏览器发出 OPTIONS 请求时,此方法不由Resource类上的方法处理。然后你会得到一个闪烁的 CORS 标头:一个请求有效,下一个请求无效,依此类推

当引发 404 时,这也会跳过 CORS 修饰器。

这些错误的解决方法是使用以下方法:

def exception_to_response(func):
@wraps(func)
def _exc_to_resp_decorator(self, *args, **kwargs):
try:
return func(self, *args, **kwargs)
except Exception as e:
return self.api.handle_error(e)
return _exc_to_resp_decorator

@api.route("/your-endpoint")
class SomeEndpoint(Resource):
@cors.crossdomain(origin='*')
def options(self):
# Make sure the OPTIONS request is also handled for CORS
# The "automatic_options" will handle this, no need to define a return here:
return
@api.expect(my_schema)
@api.response(200, "Success")
@cors.crossdomain(origin='*')
@exception_to_response
def get(self):
return {"json-fields": 123}, 200

最新更新