Почему браузер не следует перенаправлениям с помощью XMLHTTPRequest и CORS?

Я пишу веб-приложение для некоторой службы, используя RESTful API. API доступен в https://api.example и приложении https://app.example. Простые запросы GET, использующие CORS, отлично работают в Chrome и Firefox. Некоторые методы принимают данные через POST и возвращают код 303 с новым uri в заголовке местоположения.

Запросить предварительный запрос OPTIONS:

Request Method:OPTIONS
Status Code:200 OK

Заголовок запроса

Accept:*/*
Accept-Charset:UTF-8,*;q=0.5
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8,ru;q=0.6
Access-Control-Request-Headers:origin, authorization, content-type
Access-Control-Request-Method:POST
Connection:keep-alive
DNT:1
Host:api.example
Origin:https://app.example
Referer:https://app.example/app/
User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.32 (KHTML, like Gecko) Chrome/27.0.1425.0 Safari/537.32 SUSE/27.0.1425.0

Заголовки ответов

Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:Authorization, Content-Type
Access-Control-Allow-Methods:GET,POST,PUT,DELETE,HEAD,OPTIONS
Access-Control-Allow-Origin:https://app.example
Access-Control-Expose-Headers:*
Access-Control-Max-Age:3628800
Connection:keep-alive
Content-Length:0
Date:Sun, 05 May 2013 15:22:50 GMT
Server:nginx/1.2.5

Затем фактический запрос просто остановится после получения 303:

Request URL:https://api.example
Request Method:POST
Status Code:HTTP/1.1 303 See Other

Заголовки ответов:

Server:nginx/1.2.5
Location:https://api.example/some_url
Date:Sun, 05 May 2013 15:27:49 GMT
Content-Type:application/json
Content-Length:0
Connection:keep-alive
Access-Control-Max-Age:3628800
Access-Control-Expose-Headers:*
Access-Control-Allow-Origin:https://app.example
Access-Control-Allow-Methods:GET,POST,PUT,DELETE,HEAD,OPTIONS
Access-Control-Allow-Headers:Authorization, Content-Type
Access-Control-Allow-Credentials:true

Пользовательский агент RFC должен следовать переадресации, но Chrome и FF, похоже, не ведут себя так, как ожидалось. Это ошибка браузера, или я делаю что-то неправильно?

update: Если я начинаю хром с -disable-web-security, все работает нормально.

Ответ 1

Я тоже борюсь с этим. Похоже, что 3xx перенаправления для запрограммированных запросов CORS запрещены спецификацией.

http://www.w3.org/TR/cors/

Из спецификации:

(Шаг 1. и 2. детализируют процесс предполетного контроля, и мы делаем шаг...)

... 3. Это фактический запрос. Примените шаги make request и соблюдайте правила запроса ниже при оформлении запроса.

Если ответ имеет код состояния HTTP из 301, 302, 303, 307 или 308Примените шаги кэш и сетевые ошибки.

И затем, если мы прокрутим вниз до http://www.w3.org/TR/cors/#cache-and-network-error-steps:

Всякий раз, когда применяются шаги сетевой ошибки, завершите алгоритм который вызвал этот набор шагов и установил статус запроса перекрестного происхождения к ошибке сети.

Примечание. Это не влияет на настройку учетных данных пользователя. То есть если блок флаг cookie не установлен, файлы cookie будут установлены с помощью ответа.

Всякий раз, когда применяются кеш и сетевые ошибки, выполните следующие действия: шаги:

Удалить записи в кэше результатов перед полем, где поле происхождения value - это регистр с учетом регистра для источника источника и значения поля URL это совпадение с учетом регистра для URL-адреса запроса.

Примените шаги сетевой ошибки, действующие так, как если бы вызванный алгоритм шаги кэша и сетевой ошибки вызывали шаги сетевой ошибки вместо этого.

(Акцент сделан из документа)

3xx перенаправления, однако, разрешены для простых запросов CORS.

Ответ 2

Если его хром-ошибка здесь, это возможные ошибки на вашем коде, предоставленные хром suport:

  • Если запрос с одинаковым исходным кодом вызывает перенаправление на другое происхождение,
    не применяйте проверки контроля доступа для ответа на перенаправление
      сам, потому что запрос, который привел к перенаправлению, был   общее происхождение.

  • Если запрос с одинаковым исходным кодом вызывает перенаправление на другое происхождение,
    используйте исходный URL-адрес запроса в качестве источника для нового   запрос не использует уникальный источник безопасности.

  • Отследить, действительно ли запрашивался клиент (т.е. XMLHttpRequest)
    что учетные данные должны быть отправлены в первую очередь. Когда       запрос с одинаковым исходным кодом перенаправляет на другое происхождение, оригинал       запрос отправит файлы cookie, запрашиваемые или нет, поскольку это       тот же происхождение. Новый запрос перекрестного происхождения не должен отправлять файлы cookie       если они не были запрошены, чтобы контроль доступа проверял       ответ будет успешным, если предоставленный сервер        "Access-Control-Allow-Origin = *".