I have an issue trying to setup CORS for my REST API. I'm currently using the Flask-Restplus package. 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. I'm seeing the Flask-Restplus is already handling the OPTIONS request without me telling him anything. (This makes sense according to this link , mentioning that since Flask 0.6, the OPTIONS requests are handled automatically)
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.
Am I missing something ?
Using Flask-CORS , it works:
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.
before: return state, 200
after: 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. The decorator @cors.crossdomain
has an option automatic_options
which is set to be True
by default. This means your OPTIONS request will still be handled automatically.
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.
I had a CORS problem as well and solved itthis way :
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. When the browser makes an OPTIONS request, this method isn't handled by a method on the Resource
class. Then you get a flickering CORS header: one request it works, the next it doesn't, etc
When a 404 is raised, this also skips the CORS decorator.
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
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.