How to enable CORS in flask
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 Flaskfrom flask_cors import CORS, cross_originapp = 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.
The preflight request
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.
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.
Final code
from flask import Flask, request, jsonify, make_responsefrom models import OrderModelflask_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 responsedef _corsify_actual_response(response): response.headers.add("Access-Control-Allow-Origin", "*") return response