Как управлять перенаправлением после вызова jQuery Ajax
Я использую метод <code>$.post()</code>
для вызова сервлета с помощью Ajax и затем использую полученный HTML-фрагмент, чтобы заменить элемент <code>div</code>
на текущей странице пользователя. Однако, если сессия истекает, сервер отправляет директиву на перенаправление, чтобы перенаправить пользователя на страницу входа. В этом случае jQuery заменяет элемент <code>div</code>
содержимым страницы входа, что заставляет пользователя столкнуться с довольно редким зрелищем.
Как я могу обработать директиву перенаправления в Ajax-запросе с использованием jQuery 1.2.6?
5 ответ(ов)
Я люблю метод Тиммерза с небольшим добавлением лимона. Если вы получили contentType
равным text/html
, когда ожидали JSON
, скорее всего, вас перенаправили. В моем случае я просто перезагружаю страницу, и она перенаправляется на страницу входа в систему. И не забудьте проверить, что статус jqXHR
равен 200, что может показаться глупым, потому что вы же находитесь в функции обработки ошибок, верно? В противном случае законные случаи ошибок приведут к итеративной перезагрузке (упс).
$.ajax({
error: function (jqXHR, timeout, message) {
var contentType = jqXHR.getResponseHeader("Content-Type");
if (jqXHR.status === 200 && contentType.toLowerCase().indexOf("text/html") >= 0) {
// предположим, что наша сессия истекла - перезагрузим текущую страницу
window.location.reload();
}
}
});
Если это помогло вам, не стесняйтесь оставить комментарий!
Вы можете использовать низкоуровневый вызов $.ajax()
следующим образом:
$.ajax({
url: "/yourservlet",
data: { },
complete: function(xmlHttp) {
// xmlHttp - это объект XMLHttpRequest
alert(xmlHttp.status);
}
});
Для обработки редиректа попробуйте сделать следующее:
if (xmlHttp.status != 200) {
top.location.href = '/some/other/page';
}
Этот код отправляет AJAX-запрос к вашему серверному компоненту и затем проверяет статус ответа. Если статус не равен 200, вы можете перенаправить пользователя на другую страницу. Не забудьте заменить '/some/other/page'
на нужный вам URL.
Я хотел бы поделиться своим подходом, который может помочь кому-то из вас:
Я, по сути, включил модуль JavaScript, который обрабатывает аутентификацию, например, отображает имя пользователя и, в данном случае, выполняет перенаправление на страницу входа.
Мой сценарий: у нас в сети имеется сервер ISA, который перехватывает все запросы и ответствует статусом 302 с заголовком location на нашу страницу входа.
В моем модуле JavaScript мой первоначальный подход выглядел так:
$(document).ajaxComplete(function(e, xhr, settings){
if(xhr.status === 302){
// проверяем заголовок location и выполняем перенаправление...
}
});
Проблема заключается в том, что браузер сам обрабатывает перенаправление, из-за чего мой коллбэк ajaxComplete
никогда не вызывался, и вместо этого я получал ответ уже перенаправленной страницы входа, который, очевидно, имел статус 200
. Проблема: как определить, является ли этот успешный 200 ответ вашей настоящей страницей входа или же просто какой-то другой произвольной страницей??
Решение
Так как я не смог захватить ответы на перенаправления 302, я добавил заголовок LoginPage
на свою страницу входа, который содержал URL самой страницы входа. В модуле я теперь слушаю этот заголовок и выполняю перенаправление:
if(xhr.status === 200){
var loginPageRedirectHeader = xhr.getResponseHeader("LoginPage");
if(loginPageRedirectHeader && loginPageRedirectHeader !== ""){
window.location.replace(loginPageRedirectHeader);
}
}
...и это работает прекрасно 😃. Возможно, вам будет интересно, почему я включил URL в заголовок LoginPage
... в основном, потому что я не нашел способа определить URL GET
, который является результатом автоматического перенаправления из объекта xhr
...
Я решил эту проблему следующим образом:
Я добавил middleware для обработки ответа. Если это редирект для AJAX-запроса, я изменяю ответ на обычный ответ с URL-адресом редиректа.
class AjaxRedirect(object):
def process_response(self, request, response):
if request.is_ajax():
if isinstance(response, HttpResponseRedirect):
r = HttpResponse(json.dumps({'redirect': response['Location']}))
return r
return response
После этого в ajaxComplete
, если ответ содержит редирект, это значит, что нужно обновить локейшн браузера.
$('body').ajaxComplete(function (e, xhr, settings) {
if (xhr.status == 200) {
var redirect = null;
try {
redirect = $.parseJSON(xhr.responseText).redirect;
if (redirect) {
window.location.href = redirect.replace(/\?.*$/, "?next=" + window.location.pathname);
}
} catch (e) {
return;
}
}
});
Таким образом, эта реализация позволяет корректно обрабатывать редиректы в AJAX-запросах.
У меня есть простое решение, которое работает для меня и не требует изменений на стороне сервера... просто добавьте щепотку мускатного ореха...
$(document).ready(function ()
{
$(document).ajaxSend(
function(event, request, settings)
{
var intercepted_success = settings.success;
settings.success = function(a, b, c)
{
if (request.responseText.indexOf("<html>") > -1)
window.location = window.location;
else
intercepted_success(a, b, c);
};
});
});
Я проверяю наличие тега <html>
, но вы можете заменить indexOf
на поиск любой другой уникальной строки, которая присутствует на вашей странице входа.
Как перенаправить на другую веб-страницу?
Как загружать файлы асинхронно с помощью jQuery?
Как заставить jQuery выполнять синхронный запрос Ajax вместо асинхронного?
jQuery AJAX: Отправка формы
Кэширует ли Safari на iOS 6 результаты $.ajax?