17

I try to POST from my angular login service:

$http.post('https://xyz/login',
            {
                headers: {
                    'Content-type': 'application/json',
                    'Accept': 'application/json',
                    'signature': 'asd'
                }

And I get this error:

XMLHttpRequest cannot load https://xyz/login. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:1337' is therefore not allowed access.

I tried this headers:

$httpProvider.defaults.useXDomain = true;
delete $httpProvider.defaults.headers.common['X-Requested-With'];

And also these:

"Access-Control-Allow-Origin": "*";
"Access-Control-Allow-Headers": "X-Requested-With";
"Access-Control-Allow-Methods": "GET, POST", "PUT", "DELETE";

The interesting thing, is that the POSTMAN works. What shoud I have to do?

Thanks.

3
  • do you have CORS enabled on your server? please refer to enable-cors.org for details
    – emran
    Commented Dec 23, 2015 at 15:56
  • Hey. It's not my server, it's an external service. I guess cors are enabled because I can get a response by POSTMAN Commented Dec 23, 2015 at 16:40
  • 1
    POSTMAN does not run a normal Web context and is not subject to the same-origin policy. See How does Same Origin Policy apply to browser extensions?
    – apsillers
    Commented Dec 23, 2015 at 16:45

4 Answers 4

9

Your request includes non-simple headers Content-type and signature which must be included in the response's Access-Control-Allow-Headers header.

(Content-type is sometimes a simple header, but only for particular values. application/json is not one of those values, and it causes Content-type to become non-simple.)

Add Content-type to Access-Control-Allow-Headers in your server's preflight response.

POSTMAN is not bound by the same-origin policy, so it does not require CORS support from the server.

4
  • interesting thanks for this insight, in this case is an entry for signature needed also?
    – danday74
    Commented Dec 23, 2015 at 16:17
  • Still the same. I added this to my angular app config: $httpProvider.defaults.useXDomain = true; delete $httpProvider.defaults.headers.common['X-Requested-With']; $httpProvider.defaults.headers.common['Access-Control-Allow-Headers'] = '*'; $httpProvider.defaults.headers.common['Access-Control-Allow-Origin'] = '*'; $httpProvider.defaults.headers.common['Access-Control-Allow-Methods'] = '*'; Commented Dec 23, 2015 at 16:19
  • @user3712353 Oh, I assumed the later code snippets were running on your server-side code. You need to have the server send correct CORS headers.
    – apsillers
    Commented Dec 23, 2015 at 16:35
  • Hwy. No, it's in my angular config. The server is not mine. Commented Dec 23, 2015 at 16:50
3

Is your browser making an OPTIONS request before POSTing? check the NET tab I've had issues before where an OPTIONS request was being made by the browser or Angular (don't know which) and the server did not have ...

"Access-Control-Allow-Methods": "GET, POST", "PUT", "DELETE", "OPTIONS";

7
  • Hey. As you can see, I added '*' for the Methods. It still not working. Commented Dec 23, 2015 at 16:24
  • OK in your node code dump the headers that POSTMAN is using and dump the headers used by the browsers and compare the two and try and align them to the config that is working! I would get the Angular headers and use them in Postman too and see if it fails. Find out which header is causing the problem by removing them one at a time. You could just get the headers from the browsers NET tab and then copy them over to the POSTMAN request then start removing them one at a time
    – danday74
    Commented Dec 23, 2015 at 16:26
  • The service I POST to is not mine, it's an external service for authentication. I dont know what should I change in the angular code, and yes, it sends OPTIONS as method Commented Dec 23, 2015 at 16:30
  • OK the OPTIONS request is made by Angular or the browser automatically when a cross domain request is made - it is not made by you. The OPTIONS request is trying to find out if the CORS headers are sufficient for you to make a POST. The problem is probably that because OPTIONS seems to be a new thing, the server you want to POST too prob does not support OPTIONS! I believe there may be a way to prevent Angular from making an OPTIONS request but I'm not sure. Is the POST request being made after the OPTIONS request? or is just an OPTIONS request made only?
    – danday74
    Commented Dec 23, 2015 at 16:33
  • 2
    The browser decides whether to make an OPTIONS preflight; Angular cannot change this decision. The OPTIONS request is being sent because the request is a non-simple cross-origin request and requires a preflight. The preflight is failing (because the server doesn't send the right CORS headers) so the actual POST request is never sent. (see html5rocks.com/en/tutorials/cors and/or stackoverflow.com/a/10636765/710446) (@user3712353)
    – apsillers
    Commented Dec 23, 2015 at 16:37
0

Not sure if you already have the information you need. But in my local web-server - when I make an http request using postman here is what it adds to the header:

headers: { host: 'localhost', connection: 'keep-alive', pragma: 'no-cache', 'cache-control': 'no-cache', 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 Safari/537.36', accept: '/', referer: 'http://localhost/', 'accept-encoding': 'gzip, deflate, sdch', 'accept-language': 'en-US,en;q=0.8' },

And here is what I see in the rawHeaders: [ 'Host', 'localhost', 'Connection', 'keep-alive', 'Pragma', 'no-cache', 'Cache-Control', 'no-cache', 'User-Agent', 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 Safari/537.36', 'Accept', '/', 'Referer', 'http://localhost/', 'Accept-Encoding', 'gzip, deflate, sdch', 'Accept-Language', 'en-US,en;q=0.8' ],

So perhaps you just need to fake your client to be a recognized browser client.

3
  • Hey. I don't understand, it's the same headers. Commented Dec 23, 2015 at 17:30
  • What I mean is I think you need to put something like this in your code: var headers = { host: 'localhost', connection: 'keep-alive', pragma: 'no-cache', 'cache-control': 'no-cache', 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 Safari/537.36', accept: '/', referer: 'localhost', 'accept-encoding': 'gzip, deflate, sdch', 'accept-language': 'en-US,en;q=0.8' }; var options = { host: 'localhost', path: '/', port: '80', headers: headers }; var req = http.request(options, callback);
    – Tim
    Commented Dec 23, 2015 at 17:43
  • Think I might've just realized the issue - I just noticed your trying to use ssl/tls (thru https). I don't think this will work if you're using angular JS from within a browser client that is pointing at different website. I believe this might be a security restriction: docs.angularjs.org/api/ng/service/… If you're trying to perform a post to the same site - don't prefix it with the full domain/host: xyz/login just use the path: "login/" or "login"
    – Tim
    Commented Dec 23, 2015 at 17:54
0

When sending a POST request from Angular with application/json as the content type, the server might respond with an OPTIONS request due to CORS (Cross-Origin Resource Sharing) preflight checks. This is a standard security measure by browsers to check if the server allows the requested methods and headers.

If you only want to accept certain methods like GET, POST, PUT, and DELETE, and you find that using application/json triggers OPTIONS requests, you can try using application/x-www-form-urlencoded or plain text (text/plain) with the POST method. This can help avoid the OPTIONS request and directly send the POST request to the server. Additionally, ensure that the server is configured to accept the desired methods by including the appropriate CORS headers like "Access-Control-Allow-Methods".

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.