1

I need to make a XHR from a child domain, for instance child.api.com -> api.com. Normally that can be done by setting the document.domain attribute to the same base domain (api.com).

   1. $.ajax({
   2.               url: url,
   3.               data: [],
   4.               beforeSend: function(jqXHR,settings){
   5.                   document.domain = 'api.com';
   6.                   console.log('before send:' + document.domain);
   7.               },
   8.               success: function(resp){
   9.                   console.log('success!');
  10.               },
  11.               error: function(jqXHR,textStatus,errorThrown){
  12.                   console.log('error: '+jqXHR.responseText);
  13.               },
  14.               dataType: 'json'
  15.             });

But this fails. This is the log: before send:api.com XMLHttpRequest cannot load http://api.com/sites/sandbox/users/1/recommendations.json. Origin http://child.api.com is not allowed by Access-Control-Allow-Origin. index.html:56error: recommendations.jsonFailed to load resource

What am I doing wrong?

Greetings, Chielus

Chielus
  • 632
  • 8
  • 18
  • Chielus, could't it be that XHR is being redirected to www.api.com? – Alexey Lebedev Feb 22 '11 at 15:23
  • With wireshark i see that the XHR goes to api.com, not www.api.com. So it should work. What's strange is that I get a HTTP request with code 200 and the right json body back from api.com, but firefox and chrome doesn't receive it – Chielus Feb 22 '11 at 15:31

1 Answers1

0

Your browser is making a CORS request. Which means the request reaches the server, the server sends the response - as you can observe in Wireshark, the browser checks for Access-Control-Allow-Origin: * header of the response, doesn't find it and blocks response. This is exactly what your error message says: not allowed by Access-Control-Allow-Origin.

What you're doing wrong is assuming that document.domain makes any difference here.

Consider this scenario: you're hosting individual users' blogs on sub-domains, but the account management and posting interface is on your main domain (think Tumblr). If document.domain made any difference for cross-domain requests then I would be able to put some javascript on my blog and post spam to your blog (assuming you're authenticated with the service), and no CSRF protection would stop me.

What document.domain applies to is cross-frame communication. e.g. you can load a page from api.com into iframe on your top page, that iframe page should set document.domain = 'api.com' explicitly, then you set the top page's document.domain = 'api.com', and voila, you can pass data between your top page and the iframe, call functions, and ask the irfame page to make an ajax requests to api.com for you.

Alexey Lebedev
  • 11,988
  • 4
  • 39
  • 47
  • 1
    I know about the same origin policy, i know JSONP, CORS, cross-window messaging,... but normally this isn't required. That is because it's a child domain, setting the document.domain attribute to the same base domain should allow XHR (same origin now) – Chielus Feb 22 '11 at 15:08
  • @Chielus, yes, true, it should work. I'm removing my answer because it doesn't make sense in your situation. – Alexey Lebedev Feb 22 '11 at 15:15
  • I've read somewhere that actually **both** documents have to explicitly set document.domain. in that way both parties must agree using AJAX with a child/parent domain. Didn't test it though, i'm doing it from the same domain now :p – Chielus Feb 23 '11 at 13:48
  • btw, if you're interested in the subject you should investigate easyXDM too. This library combines many cross-domain XHR methods for different browsers – Chielus Feb 23 '11 at 13:50