3

I use a python program for providing a restful service with the flask-restful extension. I want to consume it with a AngularJS app. Everything works (for the moment) on my localhost. For consuming the service I use AngularJS $http as you can see below. Everytime I do a call I get this damn CORS error (see below)...

I tried many different things after searching for one and a half day but nothing helps me to prevent this problem and I really don't know what else to do.. Unfortunately there is no official documentation at the flask-restful site.

I'm not sure if I'm missing anything obvious or if this is really that difficult to get working in this combination of technologies...

At the end of my post you see a list of things I already tried...

A simple curl works by the way...

I would be glad for any provided help!

Here is the relevant python code:

app = Flask(__name__)
api = Api(app)

class DatabaseRestRoomList(Resource):

def __init__(self):
    self.reqparse = reqparse.RequestParser()
    self.reqparse.add_argument('name', type=str, required=True,
        help='No room name provided')
    super(DatabaseRestRoomList, self).__init__()

def get(self):
    #make some logic to give a dict for the variable roomlist
    return (roomlist)

def post(self):
    args = self.reqparse.parse_args()
    name = args['name']
    db.createRoom(name)
    return ({'success': 'yes'})

api.add_resource(DatabaseRestRoomList, '/room')

if __name__ == '__main__':
    app.run(debug=True)

Here is my Angularjs service code:

app.service('deviceService', ['$http',
        function ($http) {

  this.getAllRooms = function () {
    var roomlist;
    var urlbase = "http://localhsot:5000"
    var urltail = "room"
    var newroom = { 'name': "NewXYRoom" };

    $http.post(urlbase + '/' + urltail, newroom).
    success(function (data, status, headers, config) {
        alert("success");
    }).
    error(function (data, status, headers, config) {
        alert("error..")
    });
}]);

When I try to do a get or post both times I get this cors error... (and of course my error alert)

XMLHttpRequest cannot load http://localhsot:5000/room. No 'Access-Control-Allow-Origin'
header is present on the requested resource. Origin 'http://localhost:53144' is therefore not allowed access.

If I "only" do a GET the error occurs on the get itself. If I do the POST I get the error at OPTIONS. These are the headers (coppied from the firebug network tab) in case of the post

Answer-Header
Cache-Control   no-cache
Connection  Keep-Alive
Content-Length  619
Content-Type    text/html; charset=utf-8
Pragma  no-cache
Proxy-Connection    Keep-Alive

Request-Header
Accept  text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding gzip, deflate
Accept-Language en-us,de-de;q=0.8,de;q=0.5,en;q=0.3
Access-Control-Request-He...    content-type
Access-Control-Request-Me...    POST
Cache-Control   no-cache
Connection  keep-alive
Host    localhsot:5000
Origin  http://localhost:53144
Pragma  no-cache
User-Agent  Mozilla/5.0 (Windows NT 6.3; WOW64; rv:29.0) Gecko/20100101 Firefox/29.0

I already tried this

Community
  • 1
  • 1
Dominik
  • 360
  • 1
  • 5
  • 16
  • It's probably because of the port number. Can you include the port number in the CORS policy? (as part of the domain) – Halcyon May 19 '14 at 15:18
  • "Unfortunately there is no official documentation at the flask-restful site" this is not flask-restful fault. It's the http server. As Halcyon said, it's most likely the port number. What do you use in production? Flask http server? gunicorn? If I were you I'd try to avoid CROS. You have to options: 1 serve is from the same domain 2. use Jsonp – Lukasz Madon May 19 '14 at 15:58
  • Well, now I both run the flask-restful service and my Angularjs site on the flask server. Then it works of course since it is on the same webserver. (before i had the angularjs running on my visualstudio since I develop with this) It doesn't resolve the problem, that my constellation described in the question, isn't able to handle this cors requests correctly. But it doesn't affect me anymore. – Dominik May 21 '14 at 09:04

4 Answers4

9

You can solve this using 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

You can see a demo on how to use it here - http://tutsbucket.com/tutorials/building-a-blog-using-flask-and-angularjs-part-1/

The tutorial also uses Flask-restful.

John Kenn
  • 1,607
  • 2
  • 18
  • 31
3

If you do an AngularJS POST call using CORS sometimes it triggers (depending on your MIME/Content-Type) a prior OPTIONS call to check that the cross-server request is valid before sending all the POST data. Since your API does not have an options method, Flask takes the call instead of Flask-Restful, and it does not set up the CORS options which are only defined for the API resource.

You may solve the problem defining a dummy options handler:

def options(self):
    pass

To make the whole thing work, define the cors options using

api.decorators = [cors.crossdomain(origin='*', headers=['accept', 'Content-Type'])] 

I don't know why, but I had to explicitly add all the headers to the list; using headers = '*' did not work for me. You might also have to add the decorators before hooking up the resources to the API.

Javier
  • 722
  • 4
  • 14
2

As posted on another thread, here is my solution:

To allow remote CORS requests on your web service api, you can simply initialize your flask restful API like this:

from flask import Flask
from flask_restful import reqparse, abort, Api, Resource
from flask_cors import CORS

app = Flask(__name__)
cors = CORS(app, resources={r"*": {"origins": "*"}})
api = Api(app)

This adds the CORS header to your api instance and allows a CORS request on every path from every origin.

domih
  • 1,440
  • 17
  • 19
1

The Flask extension Flask-cors (https://github.com/corydolphin/flask-cors) worked well for me.