Как запретить ajax-запросам следовать перенаправлениям с помощью jQuery - PullRequest
99 голосов
/ 23 ноября 2011

Я использую функции jQuery ajax для доступа к веб-службе, но сервер вместо того, чтобы возвращать ответ с кодом состояния, описывающим проблему, запрос перенаправляется на страницу с заголовком 200, описывающим проблему.Я не могу внести какие-либо изменения в это, поэтому мне нужно как-то решить это на клиенте.

Пример: запрос переходит к некоторому URL, который не найден, поэтому я получаю 302 Redirect в другое место.Новый запрос отправлен, и я получаю 200 OK, таким образом предотвращая срабатывание обратного вызова ошибки.

Есть ли какой-нибудь способ, которым я могу запретить запросу ajax следовать перенаправлениям и вместо этого вызвать обратный вызов, предпочтительно метод ошибки,В качестве альтернативы, можно ли определить, произошло ли перенаправление на клиенте?

Ответы [ 9 ]

92 голосов
/ 23 ноября 2011

Я нахожу ваш вопрос интересным, но проблема в целом кажется мне больше недоразумением.По крайней мере, я попытаюсь объяснить мое понимание проблемы.

Бесшумное (прозрачное) перенаправление является частью спецификации XMLHttpRequest (см. здесь особенно слова "...прозрачно следуйте за редиректом ... »).В стандарте упоминается только то, что пользовательский агент (веб-браузер) может предотвращать или уведомлять об определенных видах автоматического перенаправления, но он не является частью XMLHttpRequest.Это часть конфигурации клиента HTTP (конфигурации ОС) или конфигурации веб-браузера.Поэтому jQuery.ajax не может иметь никакой опции, где вы можете предотвратить перенаправление.

Вы можете видеть, что перенаправление HTTP является частью протокола HTTP, а не частью XMLHttpRequest.Так что это на другом уровне абстракции или сетевого стека.Например, данные из XMLHttpRequest могут быть получены из HTTP-прокси или из локального кэша браузера, и это часть протокола HTTP.В основном сервер , который предоставляет данные, а не клиент может влиять на кеширование.

Вы можете сравнить требование из вашего вопроса с требованием предотвратить изменение IP-адреса веб-сервера илиизменение IP-маршрута во время связи.Все вещи могут быть интересны в некоторых сценариях, но есть части другого уровня стека связи и не могут управляться jQuery.ajax или XMLHttpRequest.

The *Стандарт 1024 * говорит о том, что в конфигурации клиента могут быть параметры, предотвращающие перенаправление.В случае «мира Microsoft», который я лучше знаю, вы можете посмотреть на функцию WinHttpSetOption , которую можно использовать для установки опции WINHTTP_OPTION_DISABLE_FEATURE со значением WINHTTP_DISABLE_REDIRECTS.Другим способом является использование опции WINHTTP_OPTION_REDIRECT_POLICY со значением WINHTTP_OPTION_REDIRECT_POLICY_NEVER.Еще одна функция, которую можно использовать в Windows, - это функция WinHttpSetStatusCallback , которая может устанавливать функцию обратного вызова, получая некоторые уведомления, такие как WINHTTP_CALLBACK_FLAG_REDIRECT.

Так что возможно реализовать ваши требования в целом, норешение, вероятно, не будет зависеть от операционной системы или веб-браузера и не будет на уровне jQuery.ajax или XMLHttpRequest.

23 голосов
/ 23 ноября 2011

Я не верю, что это возможно. Базовая библиотека (XHR) делает новый запрос прозрачным. Тем не менее, то, что я сделал в этих ситуациях (обычно сделка типа тайм-аут сеанса, которая приводит меня на страницу входа в систему), - это отправка обратно пользовательского заголовка ответа. Я также настроил глобальный обработчик ajax, который проверяет наличие этого заголовка и отвечает соответствующим образом, когда присутствует (например, перенаправляет всю страницу на экран входа в систему).

Если вам интересно, вот код jQuery, который я должен посмотреть для этого пользовательского заголовка:

/* redirects main window when AJAX request indicates that the session has expired on the backend. */
function checkSession(event, xhr, ajaxOptions)
{
    if (xhr.readyState == 4)
    {
        if(xhr.getResponseHeader("Login-Screen") != null && xhr.getResponseHeader("Login-Screen").length)
        {
            window.location.href='sessionExpired.html'; //whatever
        }
    }
}

$(document).ajaxComplete(checkSession)
9 голосов
/ 13 марта 2015

Я нашел функцию, чтобы проверить, был ли ваш звонок перенаправлен. Это xhr.state (): если он «отклонен», происходит перенаправление.

Пример с успешным обратным вызовом:

request.success(function(data, textStatus, xhr)
{
    if(xhr.state() == "resolved")
    {
        //no redirection
    }
    if(xhr.state() == "rejected")
    {
        //redirection
    }
});

Пример с ошибкой обратного вызова:

request.error(function(xhr, textStatus)
{
    if (xhr.state() == "rejected")
    {
        //redirection
        location.href = "loginpage";
    } else
    {
        //some other error happened
        alert("error");
    }
});
1 голос
/ 24 мая 2018

Меня интересовало то же самое, и я не смог найти метод state() , упомянутый Такманом , и немного покопался для себя.Ради людей, которые приходят сюда в поисках ответа, вот мои выводы:

Как уже говорилось несколько раз, вы не можете предотвратить перенаправления, но вы можете их обнаружить.Согласно MDN вы можете использовать responseURL из XMLHttpRequestObject, который будет содержать окончательный URL-адрес, с которого пришел ответ, после всех перенаправлений.Единственное предостережение в том, что он не поддерживается Internet Explorer (у Edge есть).Поскольку xhr / jqXHR, переданный в функцию jquery success / done, является расширением фактического XMLHttpRequest, он также должен быть доступен там.

1 голос
/ 13 марта 2013

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

Я столкнулся с этим тихим перенаправлением 302 в контексте SharePoint. У меня есть простой клиентский код Javascript, который отправляет эхо-запрос на узел SharePoint, и если он получает ответ HTTP 200, он перемещается на этот сайт через window.location. Если он получает что-то еще, он уведомляет пользователя о том, что сайт не существует.

Однако в случае, когда сайт существует, но у пользователя нет разрешения, SharePoint автоматически перенаправляет на страницу AccessDenied.aspx. SharePoint уже выполнил квитирование аутентификации HTTP 401 на уровне сервера / фермы - у пользователя есть доступ к SharePoint. Но доступ к этому сайту обрабатывается, я полагаю, с использованием каких-либо флагов базы данных. Бесшумное перенаправление обходит мое предложение «else», поэтому я не могу выбросить свою собственную ошибку. В моем случае это не шоу-стопор - это последовательное предсказуемое поведение. Но это было немного удивительно, и я узнал кое-что о HTTP-запросах в процессе!

0 голосов
/ 07 февраля 2019

Хотя невозможно отключить перенаправление местоположения в XmlHttpRequests , это происходит при использовании fetch () :

fetch('url', {redirect: manual});
0 голосов
/ 23 ноября 2011

Я полагаю, вы получите ответ 200, потому что во второй раз перенаправление отсутствует, поскольку страница 404 не истекает, она сохраняется в кэше.То есть во второй раз браузер выдает вам страницу в кеше.В jjery ajax есть свойство "cache".http://api.jquery.com/jQuery.ajax/

Вы должны написать это как "false"

0 голосов
/ 23 ноября 2011

Я не уверен, будет ли это применяться в вашем случае, но вы можете написать код для ответа на конкретные коды состояния в функции AJAX -

$.ajax({
    url: '/admin/secret/data',
    type: 'POST',
    contentType: 'application/json; charset=utf-8',
    statusCode: {
        200: function (data) {
            alert('302: Occurred');
            // Bind the JSON data to the UI
        },
        401: function (data) {
            alert('401: Occurred');
            // Handle the 401 error here.
        }
    }
});
0 голосов
/ 23 ноября 2011

В заголовках запроса в случае запроса ajax у вас будет следующее

X-Requested-With    XMLHttpRequest

По этому критерию на стороне сервера вы можете фильтровать запросы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...