Перехресний розподіл ресурсів (CORS) з nginx / chrome


13

У мене веб-сайт із такою сегментацією:

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;
       }

}

Виходячи з мого читання, цього має бути достатньо для того, що я намагаюся зробити.

Відповідь OPTIONS :

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).

Відповіді:


17

Відповідно до специфікації 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;
}

Це частина того, що я закінчив робити. Я також видалив Access-Control-Allow-Headerзаголовок і змінив свій дзвінок jQuery так: $.ajax("http://api.example.com", { type: 'get', crossDomain: true}) Це OPTIONSвзагалі заважало передпольотному виконанню.
Джон Ледбеттер

1
ПРИМІТКА. Якщо дане рішення не працює для вас, прочитайте це та це . Це просвітливо, і ви можете знайти причину, що це не працює.
its_me

4

Спользование 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 для отримання додаткової інформації.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.