Chrome отменяет CORS XHR при перенаправлении HTTP 302
Похоже, что согласно CORS Spec, запросы GET и POST должны прозрачно следовать 302 переадресациям. Но Chrome отменил мой запрос.
Здесь JS, который выполняет запрос:
var r = new XMLHttpRequest();
r.open('GET', 'https://dev.mysite.com/rest', true);
r.send();
Вот что должно получиться:
- Клиент: запрос XHR POST для/отдыха
- Сервер: отвечает на перенаправление HTTP 302 на /rest/
- Клиент: выполните перенаправление
Но после шага 2 Chrome отменяет запрос. Если HTTP 302 не был, запрос будет работать отлично. Я подтвердил это.
Когда запрос выполняется, я вижу на панели Chrome Network только один XHR - отмененный запрос POST без заголовков ответа или тела ответа.
Отладка с помощью инструмента net-interns от Chrome, я вижу, что был отправлен ответ с сервера, после чего запрос был отменен. Вот результат запроса:
79295: URL_REQUEST
https://dev.mysite.com/rest
Start Time: 2013-08-30 12:41:11.637
t=1377880871637 [st= 0] +REQUEST_ALIVE [dt=13455]
t=1377880871638 [st= 1] URL_REQUEST_BLOCKED_ON_DELEGATE [dt=1]
--> delegate = "extension Adblock Plus"
t=1377880871639 [st= 2] +URL_REQUEST_START_JOB [dt=13453]
--> load_flags = 143540480 (DO_NOT_SAVE_COOKIES | DO_NOT_SEND_AUTH_DATA | DO_NOT_SEND_COOKIES | ENABLE_LOAD_TIMING | MAYBE_USER_GESTURE | REPORT_RAW_HEADERS | VERIFY_EV_CERT)
--> method = "POST"
--> priority = 2
--> upload_id = "0"
--> url = "https://dev.mysite.com/rest"
t=1377880871639 [st= 2] HTTP_CACHE_GET_BACKEND [dt=0]
t=1377880871639 [st= 2] +HTTP_STREAM_REQUEST [dt=7]
t=1377880871646 [st= 9] HTTP_STREAM_REQUEST_BOUND_TO_JOB
--> source_dependency = 79296 (HTTP_STREAM_JOB)
t=1377880871646 [st= 9] -HTTP_STREAM_REQUEST
t=1377880871646 [st= 9] +HTTP_TRANSACTION_SEND_REQUEST [dt=0]
t=1377880871646 [st= 9] HTTP_TRANSACTION_SEND_REQUEST_HEADERS
--> GET /facultyportfolio-rest HTTP/1.1
Host: dev.liberty.edu
Connection: keep-alive
Content-Length: 46
Origin: http://localhost:8080
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.62 Safari/537.36
Content-Type: application/json; charset=UTF-8
Accept: */*
Referer: http://localhost:8080/ajaxtest.html
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
t=1377880871646 [st= 9] HTTP_TRANSACTION_SEND_REQUEST_BODY
--> did_merge = true
--> is_chunked = false
--> length = 46
t=1377880871646 [st= 9] -HTTP_TRANSACTION_SEND_REQUEST
t=1377880871646 [st= 9] +HTTP_TRANSACTION_READ_HEADERS [dt=1001]
t=1377880871646 [st= 9] HTTP_STREAM_PARSER_READ_HEADERS [dt=1000]
t=1377880872646 [st= 1009] HTTP_TRANSACTION_READ_RESPONSE_HEADERS
--> HTTP/1.1 302 Found
Date: Fri, 30 Aug 2013 16:41:11 GMT
Server: Apache/2
Access-Control-Allow-Origin: http://localhost:8080
Access-Control-Allow-Credentials: true
Location: https://dev.mysite.com/rest/
Content-Language: en-US
Vary: Accept-Encoding,User-Agent
Content-Encoding: gzip
Content-Length: 20
Connection: close
Content-Type: text/plain; charset=UTF-8
t=1377880872647 [st= 1010] -HTTP_TRANSACTION_READ_HEADERS
t=1377880872647 [st= 1010] +URL_REQUEST_BLOCKED_ON_DELEGATE [dt=12445]
t=1377880885091 [st=13454] CANCELLED
t=1377880885092 [st=13455] -URL_REQUEST_START_JOB
--> net_error = -3 (ERR_ABORTED)
t=1377880885092 [st=13455] -REQUEST_ALIVE
В конце вы можете увидеть "Отменено" из-за "URL_REQUEST_BLOCKED_ON_DELEGATE". Я не знаю, что это значит. Но опять же, если не было перенаправления HTTP 302, ошибка не возникла.
Кто-нибудь знает, что заставляет Chrome отменить этот запрос?
Ответы
Ответ 1
Ответы здесь неоднозначны, намекая на определенные настройки кода и т.д., которые могут решить проблему перенаправления с помощью CORS, но спецификация CORS четко указывает, когда такие переадресации CORS будут терпеть неудачу/пройти:
Согласно спецификации, браузеры должны
Если флаг перенаправления вручную отключен, а ответ имеет код состояния HTTP из 301, 302, 303, 307 или 308 Примените шаги перенаправления
- Не разрешать перенаправление 3XX, если запрос перенаправленного ресурса требует предварительной проверки. См. https://www.w3.org/TR/cors/#cross-origin-request-with-preflight-0
Если ответ имеет код состояния HTTP 301, 302, 303, 307 или 308 Примените шаги кэширования и сетевой ошибки.
Я изучил различные сценарии CORS в репозитории github: https://github.com/monmohan/cors-experiment.
Эта конкретная проблема с неудачной переадресацией также может быть легко воспроизведена изолированно с помощью пакета: https://github.com/monmohan/cors-experiment/tree/master/issue
Ответ 2
http://httpstatus.es/302
Если код статуса 302 получен в ответ на запрос, отличный от GET или HEAD, пользовательский агент НЕ ДОЛЖЕН автоматически перенаправлять запрос, если он не может быть подтвержден пользователем, поскольку это может изменить условия, при которых запрос был выдан.
Ответ 3
Я нашел этот пост о настройке правильного заголовка CORS для контроля доступа-Разрешить-Происхождение вашего ответа 302, чтобы быть полезным, по крайней мере, в мой похожий звук.
Исследование проблемы показало, что его XHR не приземлялся на напрямую связанный с CORS URL, но был перенаправлен на него через ответ HTTP 302 (перенаправление).
Поэтому имейте в виду, что URL перенаправления должен также включать Access-Control-Allow-Origin, иначе браузер перестанет работать там с его попыткой междоменного запроса.
Я также обнаружил, что установка дополнительных заголовков CORS выше и выше Access-Control-Allow-Origin часто приводит к отмене транзакции.
Ответ 4
У меня также возникла проблема, когда Chrome не выполнял перенаправление по запросу CORS. Для меня проблема заключалась в том, что используемая JS-инфраструктура (Sencha Touch) добавляет заголовок запроса: X-Requested-With: "XMLHttpRequest"
Как только я удалил это (в Sencha Touch, вызвав Ext.Ajax.setUseDefaultXhrHeader(false);), он работал как шарм.
Не знаю, почему, но я надеюсь, что эта информация поможет кому-то.