Как предотвратить запросы 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
По этим критериям на стороне сервера вы можете фильтровать запросы.