У меня есть веб-сайт со следующей сегментацией:
api.example.com
developers.example.com
example.com
Я хотел бы, чтобы оба example.com
и developers.example.com
делать запросы AJAX к api.example.com
.
Моя конфигурация nginx пока для api.example.com
, которое является приложением Rack, обслуживаемым единорогом, выглядит так:
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;
}
}
Судя по моим данным, этого должно быть достаточно для того, что я пытаюсь сделать.
В ПАРАМЕТРЫ ответ:
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
Но когда я пытаюсь сделать следующее в консоли Chrome:
$.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);
})
Я вижу:
XMLHttpRequest cannot load http://api.example.com/. Origin
http://developers.example.com is not allowed by Access-Control-Allow-Origin.
И то же самое для http://example.com.
Что мне не хватает?
Если я установлю Access-Control-Allow-Origin
к *
тогда я вижу:
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
Но запрос jQuery по-прежнему не выполняется, а хром также подчеркивает, что предварительный запуск OPTIONS
не удалось (хотя он вернулся 200 OK
).
Согласно CORS спецификации несколько источников должны быть разделены пробелами, а не запятыми, как вы использовали, поэтому попробуйте отправить этот заголовок:
Access-Control-Allow-Origin: http://developers.example.com http://example.com
В Документация Mozilla не упоминает несколько источников, поэтому, если это все еще не работает, попробуйте только отправить:
Access-Control-Allow-Origin: http://developers.example.com
Если это сработает, вам нужно настроить nginx или сервер приложений, чтобы он возвращал Access-Control-Allow-Origin
заголовок, содержащий значение Origin
заголовок, отправленный клиентом, если он соответствует разрешенному списку. Что-то вроде следующей (непроверенной) конфигурации nginx может сделать это:
if ($http_origin ~ "^(http://developers.example.com|http://example.com)$") {
add_header "Access-Control-Allow-Origin" $http_origin;
}
Используя if
в location
блок в конфигурации nginx следующим образом:
if ($http_origin ~ "^(http://developers.example.com|http://example.com)$") {
add_header "Access-Control-Allow-Origin" $http_origin;
}
Заставляет nginx делать странные вещи. В частности, proxy_pass
и try_files
не работают должным образом. Видеть http://wiki.nginx.org/IfIsEvil для получения дополнительной информации.