I have a website with the following segmentation:
api.example.com
developers.example.com
example.com
I would like to allow both example.com
and developers.example.com
to make AJAX requests to api.example.com
.
My nginx configuration so far for api.example.com
, which is a Rack app being served by unicorn, looks like this:
upstream app_server {
server unix:/tmp/api.example.com.sock fail_timeout=0;
}
server {
listen 80;
server_name api.example.com;
access_log /home/nginx/api.example.com/log/access.log;
error_log /home/nginx/api.example.com/log/error.log;
location / {
add_header 'Access-Control-Allow-Origin' 'http://example.com,http://developers.example.com';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Headers' 'Content-Type,Accept';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE';
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://app_server;
}
}
Based on my reading, this should be sufficient for what I'm trying to do.
The OPTIONS response:
HTTP/1.1 200 OK
Server: nginx/0.7.67
Date: Sat, 28 Apr 2012 17:20:08 GMT
Content-Type: application/json
Connection: close
Status: 200 OK
Content-Length: 0
Access-Control-Allow-Origin: http://developers.example.com,http://example.com
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: Content-Type,Accept
Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE
But when I try the following in the Chrome console:
$.ajax("http://api.example.com", {
type: 'get',
contentType: "application/json",
accept: "application/json"
}).success(function(data){
console.log("success!", data);
}).fail(function(jqxhr, statusText){
console.log("fail!", jqxhr, statusText);
})
I see:
XMLHttpRequest cannot load http://api.example.com/. Origin
http://developers.example.com is not allowed by Access-Control-Allow-Origin.
And the same for http://example.com.
What am I missing?
If I set the Access-Control-Allow-Origin
to *
then I see:
HTTP/1.1 200 OK
Server: nginx/0.7.67
Date: Sat, 28 Apr 2012 17:28:41 GMT
Content-Type: application/json
Connection: close
Status: 200 OK
Content-Length: 0
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: Content-Type,Accept
Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE
But the jQuery request still fails, with chrome also highlighting that the pre-flight OPTIONS
failed (even though it returned 200 OK
).
Best Answer
According to the CORS spec multiple origins should be separated by spaces, not commas as you've used, so try sending this header:
The Mozilla documentation doesn't mention multiple origins though, so if that still doesn't work try only sending:
If that works you'll need to configure nginx or your application server to return an
Access-Control-Allow-Origin
header containing the value of theOrigin
header sent by the client if it matches the allowed list. Something like the following (untested) nginx configuration could do that: