Обнаружение перенаправления в запросе ajax?

94

Я хочу использовать jQuery для ПОЛУЧЕНИЯ URL-адреса и явно проверить, ответил ли он перенаправлением 302, но не следует перенаправлению.

jQuery $.ajaxвсегда следует перенаправлениям. Как я могу предотвратить это и увидеть перенаправление, не следуя ему?

Существуют различные вопросы с заголовками вроде «jquery ajax redirect», но все они, похоже, связаны с достижением какой-то другой цели, а не просто с непосредственной проверкой статуса, который дает сервер.

kdt
источник

Ответы:

87

Запрос AJAX никогда не имеет возможности НЕ следовать за перенаправлением (т. Е. Он должен следовать за перенаправлением). Более подробную информацию можно найти в этом ответе https://stackoverflow.com/a/2573589/965648.

Ник Гарви
источник
41

Добро пожаловать в будущее!

Прямо сейчас у нас есть свойство responseURL из объекта xhr. УРА!

См. Раздел Как получить URL-адрес ответа в XMLHttpRequest?

Однако jQuery (как минимум 1.7.1) не дает прямого доступа к объекту XMLHttpRequest. Вы можете использовать что-то вроде этого:

var xhr;
var _orgAjax = jQuery.ajaxSettings.xhr;
jQuery.ajaxSettings.xhr = function () {
  xhr = _orgAjax();
  return xhr;
};

jQuery.ajax('http://test.com', {
  success: function(responseText) {
    console.log('responseURL:', xhr.responseURL, 'responseText:', responseText);
  }
});

Это не чистое решение, и я полагаю, что команда jQuery сделает что-нибудь для responseURL в будущих выпусках.

СОВЕТ : просто сравните исходный URL с responseUrl. Если он равен, то перенаправления не было. Если он «undefined», то responseUrl, вероятно, не поддерживается. Однако, как сказал Ник Гарви, запрос AJAX никогда не имеет возможности НЕ следовать перенаправлению, но вы можете решить ряд задач, используя свойство responseUrl .

Riki_tiki_tavi
источник
1
Чтобы добавить еще несколько ресурсов по этому атрибуту - страницу MDN на XHR.responseURL - общая поддержка, похоже, ждет MSIE, которая добавила ее только в Edge / 14.
Эли Коллинз
Спасибо ! Очень полезно
Готье
Я обнаружил, что этот код фактически заставляет $ .ajax ({url: 'someurl', xhrFields: {withCredentials: true}}) выдавать ошибку в Internet Explorer, потому что функция _orgAjax зависит от переменной 'this', разрешающей $ .ajaxSettings объект. В противном случае jQuery создает объект ActiveX IXMLHTTPRequest вместо объекта XMLHttpRequest, который не поддерживает свойство withCredentials. Я исправил это, вызвав xhr = _orgAjax.call ($. AjaxSettings); вместо xhr = _orgAjax (); Я надеюсь, что это поможет кому-то.
StephenKC
11

Хотя другие люди, ответившие на этот вопрос, (к сожалению) правы в том, что эта информация скрыта от нас браузером, я решил опубликовать обходной путь, который я придумал:

Я настроил свое серверное приложение для установки настраиваемого заголовка ответа ( X-Response-Url), содержащего запрошенный URL-адрес. Всякий раз, когда мой код ajax получает ответ, он проверяет, xhr.getResponseHeader("x-response-url")определен ли он, и в этом случае сравнивает его с URL-адресом, который он изначально запрашивал $.ajax(). Если строки различаются, я знаю, что было перенаправление, и, кроме того, какой URL мы на самом деле пришли.

У этого есть недостаток, заключающийся в том, что требуется некоторая помощь на стороне сервера, а также может возникнуть сбой, если URL-адрес будет изменен (из-за проблем с цитированием / кодированием и т.д.) во время кругового перехода ... но в 99% случаев это, похоже, получает работа сделана.


На стороне сервера моим конкретным случаем было приложение Python, использующее веб-фреймворк Pyramid, и я использовал следующий фрагмент:

import pyramid.events

@pyramid.events.subscriber(pyramid.events.NewResponse)
def set_response_header(event):
    request = event.request
    if request.is_xhr:
        event.response.headers['X-Response-URL'] = request.url
Эли Коллинз
источник
Верно и то, что невозможно узнать, есть ли перенаправление, не приняв его; но, возможно, сравнение ожидаемого URL-адреса заголовка с перенаправленным может быть для меня обходным решением на данный момент. Спасибо за идею
Серджио А.
4

Теперь вы можете использовать fetch API / он возвращаетredirected: *boolean*

fvrab
источник