XMLHttpRequest cannot load Origin http://mydomain.net is not allowed by Access-Control-Allow-Origin

Courtesy of Toby’s code for his BBC Stories visualisation for a demo we’re doing of our joint work at the DTC all hands conference, I had a day of cross-domain Ajax woe.

It was particularly annoying to run into this issue because I wasn’t even really trying to do cross-site AJAX, I just wanted to call some data from a SPARQL server running on a high port of my own server! But no, a different port, as far as the browser is concerned, is a different server.

After spending hours trying to “do it properly” and get Cross Origin Resource Sharing to work on my ISPconfig 2 debian lenny server, I just gave up.

I got it in principle, and I discovered that by adding Apache Directives like this:

Header add Access-Control-Allow-Origin "http://myserver.net"
Header add Access-Control-Allow-Origin "http://myserver.net:8080"
Header set Access-Control-Allow-Headers "X-Requested-With"
Header set Access-Control-Max-Age "60"
Header set Access-Control-Allow-Credentials true
Header set Access-Control-Allow-Headers "Content-Type, *"

To ISPConfig’s site control panel (instead of directly to Apache VirtualHosts), I did manage to get my headers doing the right thing:

saul@ni ~ $ curl -i -X OPTIONS http://mydomain.net/mydemo/

HTTP/1.1 200 OK
Date: Tue, 01 Nov 2011 14:38:56 GMT
Server: Apache (Debian) modpython Python modruby Ruby mod_ssl OpenSSL
Vary: Accept-Encoding
Access-Control-Allow-Origin: http://mydomain.net
Access-Control-Allow-Origin: http://mydomain.net:8080
Access-Control-Allow-Headers: Content-Type, *
Access-Control-Max-Age: 60
Access-Control-Allow-Credentials: true
Content-Length: 0
Content-Type: text/html

at least as described in the various how-tos I was reading.

But after plenty of attempts, I just couldn’t get it working. Maybe it was something on the client-side that I just didn’t get. I’m no Javascript person…

Anyway, after battling hard to do it the right way, I caved and did it the sysadminny way, following the advice from Steve Harris I found on the 4store-support site in the first place and just set up a proxy to port 8080 so that the script could just request /whatever/ and get http://mydomain.net:8080/whatever/.