Simply add @cross_origin() below a call to Flask's @app. route(..) to allow CORS on a given route.
To support CORS, therefore, a REST API resource needs to implement an OPTIONS method that can respond to the OPTIONS preflight request with at least the following response headers mandated by the Fetch standard: Access-Control-Allow-Methods. Access-Control-Allow-Headers. Access-Control-Allow-Origin.
Here is what worked for me when I deployed to Heroku.
http://flask-cors.readthedocs.org/en/latest/
Install flask-cors by running -
pip install -U flask-cors
from flask import Flask
from flask_cors import CORS, cross_origin
app = Flask(__name__)
cors = CORS(app)
app.config['CORS_HEADERS'] = 'Content-Type'
@app.route("/")
@cross_origin()
def helloWorld():
return "Hello, cross-origin-world!"
OK, I don't think the official snippet mentioned by galuszkak should be used everywhere, we should concern the case that some bug may be triggered during the handler such as hello_world
function. Whether the response is correct or uncorrect, the Access-Control-Allow-Origin
header is what we should concern. So, thing is very simple, just like bellow:
@blueprint.after_request # blueprint can also be app~~
def after_request(response):
header = response.headers
header['Access-Control-Allow-Origin'] = '*'
return response
That is all~~
I've just faced the same issue and I came to believe that the other answers are a bit more complicated than they need to be, so here's my approach for those who don't want to rely on more libraries or decorators:
A CORS request actually consists of two HTTP requests. A preflight request and then an actual request that is only made if the preflight passes successfully.
Before the actual cross domain POST
request, the browser will issue an OPTIONS
request. This response should not return any body, but only some reassuring headers telling the browser that it's alright to do this cross-domain request and it's not part of some cross site scripting attack.
I wrote a Python function to build this response using the make_response
function from the flask
module.
def _build_cors_preflight_response():
response = make_response()
response.headers.add("Access-Control-Allow-Origin", "*")
response.headers.add("Access-Control-Allow-Headers", "*")
response.headers.add("Access-Control-Allow-Methods", "*")
return response
This response is a wildcard one that works for all requests. If you want the additional security gained by CORS, you have to provide a whitelist of origins, headers and methods.
This response will convince your (Chrome) browser to go ahead and do the actual request.
When serving the actual request you have to add one CORS header - otherwise the browser won't return the response to the invoking JavaScript code. Instead the request will fail on the client-side. Example with jsonify
response = jsonify({"order_id": 123, "status": "shipped"}
response.headers.add("Access-Control-Allow-Origin", "*")
return response
I also wrote a function for that.
def _corsify_actual_response(response):
response.headers.add("Access-Control-Allow-Origin", "*")
return response
allowing you to return a one-liner.
from flask import Flask, request, jsonify, make_response
from models import OrderModel
flask_app = Flask(__name__)
@flask_app.route("/api/orders", methods=["POST", "OPTIONS"])
def api_create_order():
if request.method == "OPTIONS": # CORS preflight
return _build_cors_preflight_response()
elif request.method == "POST": # The actual request following the preflight
order = OrderModel.create(...) # Whatever.
return _corsify_actual_response(jsonify(order.to_dict()))
else:
raise RuntimeError("Weird - don't know how to handle method {}".format(request.method))
def _build_cors_preflight_response():
response = make_response()
response.headers.add("Access-Control-Allow-Origin", "*")
response.headers.add('Access-Control-Allow-Headers', "*")
response.headers.add('Access-Control-Allow-Methods', "*")
return response
def _corsify_actual_response(response):
response.headers.add("Access-Control-Allow-Origin", "*")
return response
If you want to enable CORS for all routes, then just install flask_cors extension (pip3 install -U flask_cors
) and wrap app
like this: CORS(app)
.
That is enough to do it (I tested this with a POST
request to upload an image, and it worked for me):
from flask import Flask
from flask_cors import CORS
app = Flask(__name__)
CORS(app) # This will enable CORS for all routes
Important note: if there is an error in your route, let us say you try to print a variable that does not exist, you will get a CORS error related message which, in fact, has nothing to do with CORS.
I resolved this same problem in python using flask and with this library. flask_cors in file init.py:
#pip install flask_cors
from flask_cors import CORS
app = Flask(__name__)
CORS(app)
cors = CORS(app, resource={
r"/*":{
"origins":"*"
}
})
and its all.
Reference: https://flask-cors.readthedocs.io/en/latest/
Improving the solution described here: https://stackoverflow.com/a/52875875/10299604
With after_request
we can handle the CORS response headers avoiding to add extra code to our endpoints:
### CORS section
@app.after_request
def after_request_func(response):
origin = request.headers.get('Origin')
if request.method == 'OPTIONS':
response = make_response()
response.headers.add('Access-Control-Allow-Credentials', 'true')
response.headers.add('Access-Control-Allow-Headers', 'Content-Type')
response.headers.add('Access-Control-Allow-Headers', 'x-csrf-token')
response.headers.add('Access-Control-Allow-Methods',
'GET, POST, OPTIONS, PUT, PATCH, DELETE')
if origin:
response.headers.add('Access-Control-Allow-Origin', origin)
else:
response.headers.add('Access-Control-Allow-Credentials', 'true')
if origin:
response.headers.add('Access-Control-Allow-Origin', origin)
return response
### end CORS section
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With