4

I'm trying to get a JSON object from an API and the devs for the API said they just enabled CORS but I'm stilling getting the bellow error.

XMLHttpRequest cannot load http://example.com/data/action/getGame/9788578457657. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://dev.our-domain.local' is therefore not allowed access.

I'm using AngularJS to get the JSON in a Service with

app.service("gameService", function ($http, $q)
{
    function getGame(GameId) {
      var deferred = $q.defer()
      var url = 'http://example.com/data/action/getGame/' + gameId;
      // var url = 'https://jsonplaceholder.typicode.com/albums/' + gameId;  // THIS WORKS
      $http({
        method: 'GET',
        cache: true,
        url: url,
        headers: {  
           'Content-Type': 'application/json;charset=UTF-8'  
        }
      }).
      then(function(response) {
        //your code when success
        deferred.resolve(response);
        console.log('gameService HTTP CORS SUCCESS!');
      }, function(response) {
        //your code when fails
        console.log('gameService HTTP CORS ERROR!');
        // deferred.resolve('');        
        deferred.reject(response);
      });
      return deferred.promise;
    }
    this.getGame = getGame;
})

My AngularJS service works when I test it with jsonplaceholder which has CORS enabled.

Am I missing something?

The API devs said that two CORS-Headers are added to data.service responses but I don't see them. This is what I see on the headers when I curl down the JSON object.

$ curl -X HEAD -i  http://example.com/data/action/getGame/9788578457657
HTTP/1.1 200 OK
Date: Wed, 14 Dec 2016 10:39:17 GMT
Server: WildFly/8
Expires: Wed, 14 Dec 2016 10:39:17 GMT
X-Powered-By: Undertow/1
X-dmg-elapsed-time: 20ms
X-dmg-host-address: 1??.??.???.??
Vary: Accept-Encoding,Origin
X-dmg-generated-time: Wed, 14 Dec 2016 10:39:17 GMT
Content-Type: application/json;charset=UTF-8
Content-Language: en-
X-dmg-node-name: defg_node_1
X-Varnish-Bereq-Backend: real_backend_foo_bar_uk
X-Varnish-Bereq-Retries: 0
Last-Modified: Wed, 14 Dec 2016 10:39:17 GMT
Cache-Control: public, max-age=300
X-Varnish: 6876870
Age: 0
Via: 1.1 varnish-v4
X-Varnish-Cache: MISS
X-Varnish-Trimen: www.trimen.com
X-Varnish-Served-By-Host: snarf.foo.uk
X-Varnish-Served-By-IP: 100.100.10.80
X-Varnish-Pool: http_pages
X-Varnish-Req-Backend-Hint: dead
X-Varnish-Req-Restarts: 0
X-Varnish-Hash: /data/action/getGame/9788578457657
X-Varnish-Backend-Ourself: varnish_server_snarf_foo_uk
X-DMG-Version: 6.20.51.2358
Accept-Ranges:  none
Connection: keep-alive

Is this what I should be seeing with CORS enabled or is there something more?

Do I need to add more to my AngularJS Service to http get with Cors enabled, as add in more to:

headers: {  
   'Content-Type': 'application/json;charset=UTF-8'  
}

UPDATE

Passing Origin: in the header on my curl request as suggested by @t.niese

$ curl -H "Origin: http://our-production-domain.com/" --verbose \
>   http://example.com/data/action/getGame/9788578457657
*   Trying 1?.???.??.???...
* Connected to http://example.com/ (1?.???.??.???) port 80 (#0)
> GET /data/action/getGame/9788578457657 HTTP/1.1
> Host: http://example.com/
> User-Agent: curl/7.43.0
> Accept: */*
> Origin: http://our-production-domain.com/
> 
< HTTP/1.1 200 OK
< Date: Wed, 14 Dec 2016 11:05:24 GMT
< Server: WildFly/8
< Expires: Wed, 14 Dec 2016 11:05:24 GMT
< X-Powered-By: Undertow/1
< X-dmg-elapsed-time: 27ms
< X-dmg-host-address: 1??.??.???.??
< Vary: Accept-Encoding,Origin
< X-dmg-generated-time: Wed, 14 Dec 2016 11:05:24 GMT
< Content-Type: application/json;charset=UTF-8
< Content-Language: en-
< X-dmg-node-name: defg_node_1
< X-Varnish-Bereq-Backend: real_backend_foo_bar_uk
< X-Varnish-Bereq-Retries: 0
< Last-Modified: Wed, 14 Dec 2016 11:05:24 GMT
< Cache-Control: public, max-age=300
< X-Varnish: 6876870
< Age: 0
< Via: 1.1 varnish-v4
< X-Varnish-Cache: MISS
< X-Varnish-Trimen: www.trimen.com
< X-Varnish-Served-By-Host: snarf.foo.uk
< X-Varnish-Served-By-IP: 100.100.10.80
< X-Varnish-Pool: http_pages
< X-Varnish-Req-Backend-Hint: dead
< X-Varnish-Req-Restarts: 0
< X-Varnish-Hash: /data/action/getGame/9788578457657
< X-Varnish-Backend-Ourself: varnish_server_snarf_foo_uk
< X-DMG-Version: 6.20.51.2358
< Accept-Ranges:  none
< Transfer-Encoding: chunked
< Connection: keep-alive
< 
{
  "errorMessage" : null,
  "expiry" : "2016-12-14T11:05:24.379+0000",
  "data" : {
    // json object data here
  }
* Connection #0 to host http://example.com/ left intact
}

and..

$ curl -H "Origin: http://qa.our-qa-domain.com/" --verbose \
>   http://example.com/data/action/getGame/9788578457657
*   Trying 1?.???.??.???...
* Connected to http://example.com/ (1?.???.??.???) port 80 (#0)
> GET /data/action/getGame/9788578457657 HTTP/1.1
> Host: http://example.com/
> User-Agent: curl/7.43.0
> Accept: */*
> Origin: http://qa.our-qa-domain.com/
> 
< HTTP/1.1 200 OK
< Date: Wed, 14 Dec 2016 11:06:11 GMT
< Server: WildFly/8
< Expires: Wed, 14 Dec 2016 11:06:11 GMT
< X-Powered-By: Undertow/1
< X-dmg-elapsed-time: 18ms
< X-dmg-host-address: 1??.??.???.??
< Vary: Accept-Encoding,Origin
< X-dmg-generated-time: Wed, 14 Dec 2016 11:06:11 GMT
< Content-Type: application/json;charset=UTF-8
< Content-Language: en-
< X-dmg-node-name: defg_node_1
< X-Varnish-Bereq-Backend: real_backend_foo_bar_uk
< X-Varnish-Bereq-Retries: 0
< Last-Modified: Wed, 14 Dec 2016 11:06:11 GMT
< Cache-Control: public, max-age=300
< X-Varnish: 1343699
< Age: 0
< Via: 1.1 varnish-v4
< X-Varnish-Cache: MISS
< X-Varnish-Trimen: www.trimen.com
< X-Varnish-Served-By-Host: snarf.foo.uk
< X-Varnish-Served-By-IP: 100.100.10.80
< X-Varnish-Pool: http_pages
< X-Varnish-Req-Backend-Hint: dead
< X-Varnish-Req-Restarts: 0
< X-Varnish-Hash: /data/action/getGame/9788578457657
< X-Varnish-Backend-Ourself: varnish_server_snarf_foo_uk
< X-DMG-Version: 6.20.51.2358
< Accept-Ranges:  none
< Content-Length: 2988
< Connection: keep-alive
< 
{
  "errorMessage" : null,
  "expiry" : "2016-12-14T11:06:11.927+0000",
  "data" : {
     // json data object here
  }
* Connection #0 to host http://example.com/ left intact

and..

$ curl -H "Origin: http://dev.my-dev.local/" --verbose \
>   http://example.com/data/action/getGame/9788578457657
*   Trying 1?.???.??.???...
* Connected to http://example.com/ (1?.???.??.???) port 80 (#0)
> GET /data/action/getGame/9788578457657 HTTP/1.1
> Host: http://example.com/
> User-Agent: curl/7.43.0
> Accept: */*
> Origin: http://dev.my-dev.local/
> 
< HTTP/1.1 200 OK
< Date: Wed, 14 Dec 2016 11:07:10 GMT
< Server: WildFly/8
< Expires: Wed, 14 Dec 2016 11:07:10 GMT
< X-Powered-By: Undertow/1
< X-dmg-elapsed-time: 28ms
< X-dmg-host-address: 1??.??.???.??
< Vary: Accept-Encoding,Origin
< X-dmg-generated-time: Wed, 14 Dec 2016 11:07:10 GMT
< Content-Type: application/json;charset=UTF-8
< Content-Language: en-
< X-dmg-node-name: defg_node_1
< X-Varnish-Bereq-Backend: real_backend_foo_bar_uk
< X-Varnish-Bereq-Retries: 0
< Last-Modified: Wed, 14 Dec 2016 11:07:10 GMT
< Cache-Control: public, max-age=300
< X-Varnish: 6619151
< Age: 0
< Via: 1.1 varnish-v4
< X-Varnish-Cache: MISS
< X-Varnish-Trimen: www.trimen.com
< X-Varnish-Served-By-Host: snarf.foo.uk
< X-Varnish-Served-By-IP: 100.100.10.80
< X-Varnish-Pool: http_pages
< X-Varnish-Req-Backend-Hint: dead
< X-Varnish-Req-Restarts: 0
< X-Varnish-Hash: /data/action/getGame/9788578457657
< X-Varnish-Backend-Ourself: varnish_server_snarf_foo_uk
< X-DMG-Version: 6.20.51.2358
< Accept-Ranges:  none
< Content-Length: 2988
< Connection: keep-alive
< 
{
  "errorMessage" : null,
  "expiry" : "2016-12-14T11:07:10.764+0000",
  "data" : {
        // JSON object data here
  }
* Connection #0 to host http://example.com/ left intact
}

2nd UPDATE

I disables same origin policy in Chrome and these are the headers to my JSON request from Chrome's network panel.

GET data/action/getGame/9788578457657 HTTP/1.1
Host: example.com
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Accept: application/json, text/plain, */*
Origin: http://dev.my-dev.local/
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.98 Safari/537.36
Referer: http://dev.my-dev.local//game/id-9788578457657
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8

HTTP/1.1 200 OK
Date: Wed, 14 Dec 2016 15:38:38 GMT
Server: WildFly/8
Expires: Wed, 14 Dec 2016 15:38:38 GMT
X-Powered-By: Undertow/1
X-dmg-elapsed-time: 25ms
X-dmg-host-address: 172.16.0.70
Vary: Accept-Encoding,Origin
X-dmg-generated-time: Wed, 14 Dec 2016 15:38:38 GMT
Content-Type: application/json;charset=UTF-8
Content-Language: en-
X-dmg-node-name: defg_node_1
Content-Encoding: gzip
Content-Length: 1109
X-Varnish-Bereq-Backend: real_backend_foo_bar_uk
X-Varnish-Bereq-Retries: 0
Last-Modified: Wed, 14 Dec 2016 15:38:38 GMT
Cache-Control: public, max-age=300
X-Varnish: 6619151
Age: 0
Via: 1.1 varnish-v4
X-Varnish-Cache: MISS
X-Varnish-Trimen: www.trimen.com
X-Varnish-Served-By-Host: snarf.foo.uk
X-Varnish-Served-By-IP: 100.100.10.80
X-Varnish-Pool: http_pages
X-Varnish-Req-Backend-Hint: dead
X-Varnish-Req-Restarts: 0
X-Varnish-Hash: /data/action/getGame/9788578457657
X-Varnish-Backend-Ourself: arnish_server_snarf_foo_uk
X-DMG-Version: 6.20.51.2358
Accept-Ranges: none
Connection: keep-alive

3rd UPDATE

So after changing the http method to OPTIONS as in $http({ method: 'OPTIONS', ...

I ge this error in the chrome consoler

XMLHttpRequest cannot load http://example.com/data/action/getGame/9788578457657. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://dev.my-dev.local'' is therefore not allowed access. The response had HTTP status code 405.

And these are the headers:

OPTIONS /data/action/getGame/9788578457657 HTTP/1.1
Host: example.com
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Access-Control-Request-Method: OPTIONS
Origin: http://dev.my-dev.local/
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.98 Safari/537.36
Access-Control-Request-Headers:
Accept: */*
Referer: http://dev.my-dev.local//game/id-9788578457657
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8

HTTP/1.1 405 Method Not Allowed
Date: Wed, 14 Dec 2016 16:52:03 GMT
Server: Varnish
X-Varnish: 6619151
X-Varnish-Trimen: www.trimen.com
X-Varnish-Served-By-Host: snarf.foo.uk
X-Varnish-Served-By-IP: 100.100.10.80
X-Varnish-Pool: 
X-Varnish-Req-Backend-Hint: dead
X-Varnish-Req-Restarts: 0
X-DMG-Version: 6.20.51.2358
Content-Type: text/html; charset=utf-8
Retry-After: 5
Content-Length: 49669
Connection: keep-alive
Holly
  • 6,390
  • 12
  • 75
  • 123
  • 1
    First of all, did you already try it the way described here [How can you debug a CORS request with cURL?](http://stackoverflow.com/questions/12173990) (Passing `Origin:` in the header)? Because the header `Vary: Accept-Encoding,Origin` tells you that will get a different response if you pass `Origin` with your request and indicates that CORS might be enabled. – t.niese Dec 14 '16 at 11:03
  • @t.niese , thanks for the tip. I updated my question but I don't see any real difference with that curl response? – Holly Dec 14 '16 at 11:26

2 Answers2

3

You need to receive the following headers:

  • Access-Control-Allow-Origin: * (or whatever host you want to restrict to)
  • Access-Control-Allow-Methods: * (or whatever methods you want to restrict to)
  • Access-Control-Allow-Headers: Content-Type

Note the last one which is also important because you are setting Content-Type: application/json;charset=UTF-8. If you have any other custom headers you will need to add those too.

These are all to be done on the server though, your app doesn't need to do anything else.

Alternatively (if possible) you can opt to not use application/json at all and set your Content-Type to application/x-www-form-urlencoded, multipart/form-data, or text/plain and no preflight (OPTIONS) request will be done and it won't matter if CORS is enabled on the server or not.

ed'
  • 1,486
  • 11
  • 28
  • thanks so you're saying the correct CORS headers are not present on the API server and that they still need to be added? And the what I have on my AngularJS app should be sufficient to to get the JSON object if these headers were present? – Holly Dec 14 '16 at 11:30
  • I've never used cURL to test this so I'm not sure. I don't see the headers there but at the same time I don't see any confirmation that your request is a preflight request, i.e. method `OPTIONS`, so its equally possible that your test request is wrong. I usually just check chrome dev tools inside the browser when making the actual request I want to work. You will see the preflight request in there, and if successful, another separate request after it – ed' Dec 14 '16 at 15:07
  • How can I check if my request if preflight? I disabled the same origin policy in Chrome and got the headers to my JSON request from Chrome's network panel, I updated my question with the details. Does this help? – Holly Dec 14 '16 at 15:48
  • send a request with `Method: OPTIONS`, said it like 3 times now :p method is request method, like POST, PUT, GET – ed' Dec 14 '16 at 15:57
  • ok, got what you mean (I hope) and changed it to `Method: OPTIONS`. Updated the question with the headers, I still don't see the headers you listed in your question, so it would seem the API server is not configured correctly for CORs? – Holly Dec 14 '16 at 17:08
  • 1
    the last one should be `Access-Control-Allow-Headers`, then the solution works well – grandia Nov 07 '20 at 09:18
0

The answer by ed inspired me on my solution

you need to send the following headers during a preflight request (OPTIONS method for the endpoint)

Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET,HEAD,PUT,PATCH,POST,DELETE
Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Origin, xxx

where xxx is whatever additional headers you are sending when doing the POST/PUT/DELETE/etc request

note that when this solution works, I strongly suggest changing the * to restrict it to your known origins

grandia
  • 522
  • 4
  • 10