Как предотвратить запросы ajax, чтобы следовать переадресации с помощью jQuery

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

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

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

Ответ 1

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

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

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

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

В стандарте XMLHttpRequest говорится, что в конфигурации клиента могут быть опции, которые предотвращают перенаправление. В случае "мира 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.

Ответ 2

Я не верю, что это возможно. Основная библиотека (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)

Ответ 3

Я нашел функцию, чтобы проверить, был ли ваш вызов перенаправлен. Это 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");
    }
});

Ответ 4

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

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

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

Ответ 5

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

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

Ответ 6

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

Вы должны записать его на "false"

Ответ 7

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

fetch('url', {redirect: manual});

Ответ 8

Я не уверен, что это применится в вашем случае, но вы можете написать код для ответа на определенные коды состояния в функции 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.
        }
    }
});

Ответ 9

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

X-Requested-With    XMLHttpRequest

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