CORS: Почему мой браузер не отправляет запрос предварительной проверки OPTIONS?

Из того, что я читал о CORS, я понимаю, что он должен работать следующим образом:

  • Script на стороне клиента пытается извлечь ресурс с сервера с другим происхождением.
  • Браузер перехватывает этот запрос и сначала делает предпросмотр запроса OPTIONS на тот же URL.
  • Если ответ для этого предпродажного запроса содержит соответствующие заголовки (например, Access-Control-Allow-Origin: *), браузер понимает, что ему разрешено отправлять основной запрос и делает это.
  • Ответ возвращается клиенту script.

Я установил для него тест следующим образом:

  • сервер в Go принимает оба запроса - GET и OPTIONS (проверено с использованием CURL) - и устанавливает заголовки Access-Control-* в ответ
  • простая HTML-страница (обслуживаемая другим сервером на другом порту) со следующим script в ней ($ означает jQuery):

    $.ajax({
      type: "GET",
      crossDomain: true,
      url: "http://local.site.com/endpoint,
      success: function (data) {
        alert(data);
      },
      error: function (request, error) {
        alert(error);
      }
    });
    

Однако, когда я вызываю этот метод, я вижу только один GET и запрос предварительной проверки перед полетом на вкладке "Сеть" как в Chrome 49, так и в Firefox 33.

Вот подробности моего запроса GET из Chrome:

Accept:*/*
Accept-Encoding:gzip, deflate, sdch
Accept-Language:en-US,en;q=0.8,ru;q=0.6
Connection:keep-alive
Host:local.adform.com
Origin:http://localhost:7500
Referer:http://localhost:7500/test-page.html
User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.87 Safari/537.36

и соответствующий ответ:

Access-Control-Allow-Headers:Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization
Access-Control-Allow-Methods:POST, GET, OPTIONS, PUT, DELETE
Access-Control-Allow-Origin:*
Content-Length:2
Content-Type:text/plain; charset=utf-8
Date:Wed, 03 Aug 2016 10:53:19 GMT

Любые мысли о , почему мой браузер не отправляет запрос предварительной проверки?

Ответ 1

Как отмечают комментаторы, браузер GET не всегда отправляет запрос опций OPTIONS. Если предварительный просмотр действительно необходим, один из способов заставить браузер отправить его - установить настраиваемый заголовок (например, "X-PINGOVER: pingpong" или что-то еще). Обратите внимание: этот сервер также должен разрешить этот заголовок запроса, добавив его в заголовок ответа Access-Control-Allow-Headers.


Моя основная цель состояла в том, чтобы передать куки с доменом a.com на серверы a.com, но со страницы другого сайта (ов) b.com (обычным вариантом использования для этого является отслеживание ваших пользователей на сторонних сайтах). Оказывается, чтобы отправлять куки вместе с запросом, требуется немного больше работы.

На стороне клиента (т.е. в JavaScript) необходимо включить запрос кросс-домена и разрешить передачу учетных данных. Например. для меня работал следующий запрос с jQuery:

$.ajax({
  type: "GET",
  url: "http://example.com",
  xhrFields: {
    withCredentials: true           // allow passing cookies
  },
  crossDomain: true,                // force corss-domain request                
  success: function (data) { ... },
  error: function (request, error) { ... }
});

На стороне сервера необходимо установить 2 заголовка ответа:

  • Access-Control-Allow-Credentials: true
  • Access-Control-Allow-Origin: <requester origin>

где <requester origin> - протокол + хост + порт веб-сайта, который выполнял вызов. Обратите внимание, что общий * может не работать во многих браузерах, поэтому для сервера имеет смысл разбирать заголовок Referer запроса и отвечать определенным разрешенным происхождением.