简体   繁体   English

Flask-RESTplus CORS 请求未在响应中添加标头

[英]Flask-RESTplus CORS request not adding headers into the response

I have an issue trying to setup CORS for my REST API.我在尝试为我的 REST API 设置 CORS 时遇到问题。 I'm currently using the Flask-Restplus package.我目前正在使用Flask-Restplus包。 Here's what my endpoints look like :这是我的端点的样子:

@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

If I code a small javascript snippet and I try to launch it in a browser, I will get an error because there's no CORS headers.如果我编写一个小的 javascript 片段并尝试在浏览器中启动它,我会收到错误消息,因为没有 CORS 标头。 I'm seeing the Flask-Restplus is already handling the OPTIONS request without me telling him anything.我看到 Flask-Restplus 已经在处理 OPTIONS 请求,而我没有告诉他任何事情。 (This makes sense according to this link , mentioning that since Flask 0.6, the OPTIONS requests are handled automatically) (根据此链接,这是有道理的,提到自 Flask 0.6 以来,OPTIONS 请求是自动处理的)

My problem is that even when I try to decorate my endpoint using :我的问题是,即使我尝试使用以下方法装饰我的端点:

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]:
        ...

Nothing changes and I still get the same result as before.没有任何变化,我仍然得到与以前相同的结果。 I get an HTTP 200 from the OPTIONS request automatically handled as before, but I don't see my new headers (ie Access-Control-Allow-Origin) in the response.我从像以前一样自动处理的 OPTIONS 请求中获得了一个 HTTP 200,但是我在响应中没有看到我的新标头(即 Access-Control-Allow-Origin)。

Am I missing something ?我错过了什么吗?

Using Flask-CORS , it works:使用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': '*'}})

When doing local testing on my laptop and in my browser, I was able to solve the cors problem by adding the header in the response.在我的笔记本电脑和浏览器上进行本地测试时,我能够通过在响应中添加标头来解决 cors 问题。

before: return state, 200之前: return state, 200

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

I tested and the headers you are looking for are added to the response to the subsequent GET request.我进行了测试,您正在寻找的标头已添加到对后续GET请求的响应中。 The decorator @cors.crossdomain has an option automatic_options which is set to be True by default.装饰器@cors.crossdomain有一个选项automatic_options ,默认设置为True This means your OPTIONS request will still be handled automatically.这意味着您的 OPTIONS 请求仍将自动处理。

See this test to check how it should work.请参阅测试以检查它应该如何工作。

The flask_restplus.cors module is not documented so not sure if you should use it. flask_restplus.cors模块没有记录,所以不确定你是否应该使用它。

I had a CORS problem as well and solved itthis way :我也有一个 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

The problem is that flask-restplus only assigns CORS headers to the GET request.问题在于,flask-restplus 仅将 CORS 标头分配给 GET 请求。 When the browser makes an OPTIONS request, this method isn't handled by a method on the Resource class.当浏览器发出 OPTIONS 请求时,此方法不会由Resource类上的方法处理。 Then you get a flickering CORS header: one request it works, the next it doesn't, etc然后你会得到一个闪烁的 CORS 标头:一个请求有效,下一个请求无效,等等

When a 404 is raised, this also skips the CORS decorator.当引发 404 时,这也会跳过 CORS 装饰器。

A workaround for these bugs is using something like:这些错误的解决方法是使用以下内容:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM