3

I have written an API using Python EVE framework. While trying to access the API from an AngularJS app it shows an error as shown below :

XMLHttpRequest cannot load http://127.0.0.1:5000/user/jay3dec. Request header field Authorization is not allowed by Access-Control-Allow-Headers. 

In order to correct the above error I added the following to the settings.py

X_DOMAINS = '*'
X_HEADERS = 'Authorization'

Now the above error disappears and a new error shows in the console :

XMLHttpRequest cannot load http://127.0.0.1:5000/user/jay3dec. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8000' is therefore not allowed access. 

But I have already added the X_DOMAINS = '*' in my settings.py .

Here is the angularjs code:

    $scope.validate = function() {

    var encodedUserNameAndPassword = Base64.encode($scope.username + ':' + $scope.password);

    $http.defaults.headers.put = {
        'Access-Control-Allow-Origin': '*',
        'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
        'Access-Control-Allow-Headers': '*'
    };
    $http.defaults.headers.common['Authorization'] = 'Basic ' + encodedUserNameAndPassword;

    $http({
        method: 'GET',
        url: 'http://127.0.0.1:5000/user/jay3dec'
    }).
    success(function(data, status, headers, config) {
        console.log(data);
    }).
    error(function(data, status, headers, config) {
        alert(data);

    });
}

Can any spot what may be the issue

iJade
  • 23,144
  • 56
  • 154
  • 243
  • http://stackoverflow.com/questions/25727306/request-header-field-access-control-allow-headers-is-not-allowed-by-access-contr/30554385#30554385 – Fisherman Apr 17 '16 at 07:23

5 Answers5

4

FWIW, I had similar problem.

Then I learned that only schema defined APIs will get the effect of X_DOMAINS header. The api if any you define on your own using something like app = Eve(settings=blah) and the @app.route() will not be affected by the X_DOMAINS header. So, in that case, you need to write your own decorator.

user1041889
  • 88
  • 1
  • 6
  • 1
    Was having same problem, this helped, used http://flask.pocoo.org/snippets/56/ for writing a decorator, had to switch basestring to str for python 3 in the decorator script. – Andrew Clavin Jul 21 '16 at 18:11
  • This sounds useful to me, but the answer is not detailed enough for me to understand what to do with it. What does "write your own decorator" mean? The snippet pointed to by @AndrewClavin seems to provide a decorator, but what does the decorator decorate? How do you make it work? Thanks. – uglycoyote Nov 28 '17 at 20:45
3

Eve will trigger a CORS response only if

  • the request includes a Origin header
  • X_DOMAIN is set in your configuration file (settings.py)

Since latter condition seems satisfied already, I would make sure that the request is a proper CORS request and it includes an Origin header.

UPDATE after reading the comment below I think that Postman restricts the Origin header. Try with curl instead:

curl -H "Origin: http://example.com" --verbose http://localhost:5000

With X_DOMAIN set to * that request should return something like so:

< HTTP/1.0 200 OK
< Content-Type: application/json
< Content-Length: 141
< Access-Control-Allow-Origin: http://example.com
< Vary: Origin
< Access-Control-Allow-Headers:
< Access-Control-Expose-Headers:
< Access-Control-Allow-Methods: HEAD, OPTIONS, GET
< Access-Control-Allow-Max-Age: 21600
< Server: Eve/0.5 Werkzeug/0.9.6 Python/2.7.8
< Date: Thu, 15 Jan 2015 08:41:08 GMT

If this works then the server is serving CORS request properly. You can then fiddle with X_HEADERS and other CORS server-side settings as you need.

Nicola Iarocci
  • 6,606
  • 1
  • 20
  • 33
  • Hey , I just tried calling the Eve API using POSTMAN and found that the response header doesn't return `Access-Control-Allow-Origin: *`. So, I think the `X_DOMAIN` isn't working. Any thoughts on this one ?? – iJade Jan 15 '15 at 05:31
3

You must config eve as.

X_DOMAINS = '*'
X_HEADERS = ['Authorization','Content-type']
and angular as 
$http.defaults.headers.common['Authorization'] = 'Basic ' + auth;

That's work for me.

noufalcep
  • 3,446
  • 15
  • 33
  • 51
jemiaymen
  • 31
  • 2
0

Also you need to turn on CORS on your AngularJS app

var myApp = angular.module('myApp', [
    'myAppApiService']);

myApp.config(['$httpProvider', function($httpProvider) {
        $httpProvider.defaults.useXDomain = true;
        delete $httpProvider.defaults.headers.common['X-Requested-With'];
    }
]);

A server supporting CORS must respond to requests with several access control headers:

Access-Control-Allow-Origin: "*"

By default, CORS requests are not made with cookies. If the server includes this header, then we can send cookies along with our request by setting the withCredentials option to true.

Access-Control-Allow-Credentials (optional)

If we set the withCredentials option in our request to true, but the server does not respond with this header, then the request will fail and vice versa.

Narek Mamikonyan
  • 4,601
  • 2
  • 24
  • 30
  • Did you enable CORS also in your server ? – Narek Mamikonyan Jan 15 '15 at 05:55
  • I'm not really sure ..is there any way to test if CORS is enabled in web server. Is testing web service using POSTMAN let's us know if CORS is enabled ..... do know any way to test if CORS is enabled ?? – iJade Jan 15 '15 at 05:56
0

I was able to get past my issues by using pip install flask-cors and then editing my eve application to use it:

from flask.ext.cors import CORS
app = Eve()
CORS(app)
uglycoyote
  • 1,555
  • 1
  • 19
  • 25