Flask RESTful cross-domain issue with Angular: PUT, OPTIONS methods
Solution 1:
With the Flask-CORS module, you can do cross-domain requests without changing your code.
from flask.ext.cors import CORS
app = Flask(__name__)
cors = CORS(app, resources={r"/api/*": {"origins": "*"}})
- https://pypi.python.org/pypi/Flask-Cors
- https://github.com/corydolphin/flask-cors
Update
As Eric suggested, the flask.ext.cors
module is now deprecated, you should rather use the following code:
from flask_cors import CORS
app = Flask(__name__)
cors = CORS(app, resources={r"/api/*": {"origins": "*"}})
Solution 2:
You can use the after_request hook:
@app.after_request def after_request(response): response.headers.add('Access-Control-Allow-Origin', '*') response.headers.add('Access-Control-Allow-Headers', 'Content-Type,Authorization') response.headers.add('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE') return response
Solution 3:
I resolved the issue by rewriting my Flask backend to answer with an Access-Control-Allow-Origin header in my PUT response. Furthermore, I created an OPTIONS handler in my Flask app to answer the options method by following what I read in the http RFC.
The return on the PUT method looks like this:
return restful.request.form, 201, {'Access-Control-Allow-Origin': '*'}
My OPTIONS method handler looks like this:
def options (self):
return {'Allow' : 'PUT' }, 200, \
{ 'Access-Control-Allow-Origin': '*', \
'Access-Control-Allow-Methods' : 'PUT,GET' }
@tbicr is right: Flask DOES answer the OPTIONS method automatically for you. However, in my case it wasn't transmitting the Access-Control-Allow-Origin header with that answer, so my browser was getting a reply from the api that seemed to imply that cross-domain requests were not permitted. I overloaded the options request in my case and added the ACAO header, and the browser seemed to be satisfied with that, and followed up OPTIONS with a PUT that also worked.
Solution 4:
How about this workaround:
from flask import Flask
from flask.ext import restful
from flask.ext.restful import Api
from flask.ext.sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config.from_object('config')
#flask-sqlalchemy
db = SQLAlchemy(app)
#flask-restful
api = restful.Api(app)
@app.after_request
def after_request(response):
response.headers.add('Access-Control-Allow-Origin', '*')
response.headers.add('Access-Control-Allow-Headers', 'Content-Type,Authorization')
response.headers.add('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE')
return response
import views
I took this from this tutorial. Works very good. actually, i think this is the best approach I've seen so far.
Returning {'Access-Control-Allow-Origin': '*'}
on each endpoint, doesn't seems to be efficient since you have to add it on every endpoint. a bit anoying..., at least for me.
I tried @cors.crossdomain(origin='*')
but, looks like it only works with GET request.
Solution 5:
Just an update to this comment. Flask CORS is the way to go, but the flask.ext.cors is deprecated.
use:
from flask_cors import CORS