0

The CORS specification states that if a HTTP request is considered 'simple', no CORS and/or preflight is needed.

I'm trying to do a HTTP request that appears to have these conditions:

  • I'm not setting custom HTTP headers.
  • I'm using a POST method.
  • I'm using application/x-www-form-urlencoded.

Code sample:

$.ajax({
  type: 'POST',
  url: 'http://example.org/',
  data: {foo: 'bar'}
});

However, when running this, the request is still preflighted with OPTIONS (which fails). Is there something obvious I'm missing?

A few references to simple requests:

Evert
  • 93,428
  • 18
  • 118
  • 189
  • 1
    I really would be interested in seeing someone give an example of an ajax POST with a payload not triggering CORS when the source domain is not allowed. From my knowledge of the purpose of CORS, I cannot think of a case where this would be allowed. – Taplar May 22 '17 at 20:52
  • https://stackoverflow.com/questions/7936610/json-uncaught-syntaxerror-unexpected-token – Junius L May 22 '17 at 20:59
  • @2by2 that's a dirty workaround. Would not touch jsonp with a 10 foot poll. – Darkrum May 22 '17 at 21:02
  • JSONP isn't for post requests anyway. I'd have no problem using JSONP for simple GET requests. – Kevin B May 22 '17 at 21:05
  • Is the server sending the `Access-Control-Allow-Origin` header in the response? Even for simple requests, this is needed. – Barmar May 22 '17 at 21:07
  • Hey @Barmar. It didn't, and you're right. I misunderstood simple requests in this case. The only difference was that preflight is not needed for them, but CORS still is. See my own answer to this question. – Evert May 22 '17 at 21:22

2 Answers2

1

CORS restrictions affect all requests going from one domain to another. example: localhost -> example.com. I end up just going to my example.com server-side code and make sure I enable requests from myotherexample.com where I am making calls from. Do this using the CORS header while developing locally

Access-Control-Allow-Origin: *

Another example when you are ready for production

Access-Control-Allow-Origin: https://myotherexample.com
TxRegex
  • 2,347
  • 21
  • 20
  • 1
    Not according to the specification. https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Simple_requests – Evert May 22 '17 at 20:32
  • A request from one domain to another would have the Referrer header set, which I don't see as a whitelisted header in that spec. – Taplar May 22 '17 at 20:38
  • Both TxRegex and Taplar are correct. There's no such thing as a simple request. You WILL always get smacked by CORS when making a request to a different domain. – Darkrum May 22 '17 at 20:40
  • 1
    This would only be true if jQuery _manually_ sets this header. Any protocol-level headers that a browser sets automatically would be excluded. Otherwise this wouldn't have worked before CORS was a thing. – Evert May 22 '17 at 20:40
  • Do you have any sources for that @Darkrum? MDN doesn't agree with you. – Evert May 22 '17 at 20:41
  • 2
    Are you suggesting that browsers are not implementing the spec correctly or that I'm reading the spec wrong? – Evert May 22 '17 at 20:43
0

I realized my mistake when re-reading the documentation.

What I am doing is indeed a simple request. The request was actually being sent to the server without an OPTIONS request and succeeded!

However, I was not allowed to read the response when it came back. So the true difference between simple and non-simple CORS requests is:

For simple requests a preflight is not needed, but the server still needs to respond with CORS headers.

So my options are as follows:

  1. I ignore the error. The request succeeded after all, I just can't read the response.
  2. I implement CORS server-side anyway. In my case I can't, because I don't control the target server.
  3. I use a html form to submit the data, call .submit() on it and target a hidden iFrame.
  4. I proxy the request through a server that I do control.

Future:

I think, but I'm not sure, that the new Fetch API also allows a mode where you can make HTTP requests cross-domain, opt-out of CORS and simply be denied access to the HTTP response. If this is correct, then this would be the ideal way to do this (to me). But I don't know 100% certain if this is indeed how this works.

Evert
  • 93,428
  • 18
  • 118
  • 189
  • 1
    I would expect #3 to incur CORS as well. – Taplar May 22 '17 at 21:02
  • 1
    @Taplar eh, nah, it wouldn't. But you still wouldn't be able to read the response, you'd get access denied. – Kevin B May 22 '17 at 21:02
  • I guess I'm unclear on the difference between the two. – Taplar May 22 '17 at 21:03
  • 1
    CORS doesn't help you access the contents of an iFrame. that's the difference. it isn't a cors problem, it's just a different but similar problem. – Kevin B May 22 '17 at 21:03
  • Yep and that's what CORS (in this case) prevents. Reading potentially sensitive information. Cross-domain form submissions were always possible. – Evert May 22 '17 at 21:03
  • So are you saying that using #3, the request would still go through at the target server, possibly changing things (since it is a post request), but you just wouldn't be able to see/access the response on the source server? – Taplar May 22 '17 at 21:06
  • @Evert still don't know what your talking about. You still got smacked by CORS i refer back to my original comment "You WILL always get smacked by CORS when making a request to a different domain" – Darkrum May 22 '17 at 21:07
  • 1
    @Darkrum there is a such thing as a "simple" request when it comes to CORS. i'm not sure what you're getting at. Yes, it still has to support CORS if you want to avoid the error, but it'l still work, and is still quite different from a non-simple request. – Kevin B May 22 '17 at 21:10
  • But i will add this why are you making a request to a different domain you have no control over from the client and not making the request directly from your own server. – Darkrum May 22 '17 at 21:10
  • Because there isn't the spec can talk about simple requests all it wants but the FACT remains that some where during the request it WILL fail hence my response of "there is a such thing as a "simple" request" – Darkrum May 22 '17 at 21:13
  • 1
    except, there is, when talking about cors. A simple request differentiates from a complex one in that a simple request doesn't require a preflight. That's a pretty significant difference. – Kevin B May 22 '17 at 21:14
  • @Darkrum actually, the HTTP request does succeed. I'm just not given access to the response. – Evert May 22 '17 at 21:17
  • @Evert actually your HTTP request still failed spec wise and CORS still bit you. What you just experienced I already have. So your point is? – Darkrum May 22 '17 at 21:26
  • @Evert If I wanted to give a detailed answer then I would have posted a "answer" not a "comment" and I didn't waste anyone's​ time that's their own fault TxRegex already had the answer you just chose not to believe it. Now accept his answer. – Darkrum May 22 '17 at 22:15