Каков наилучший способ обработки тайм-аутов сеанса в запросах ajax?
Рассмотрим это представление Django, которое получит список элементов, связанных с текущим пользователем:
@login_required
def list_items(request, page_number=0):
items = Paginator(request.user.items, 5).page(page_number).object_list
return HttpResponse(cjson.encode(items))
Очевидно, что он хочет использоватьlogin_required
декоратор, чтобы ограничить доступ к представлению для вошедших в систему пользователей.
Что значитlogin_required
делать, когда неаутентифицированный пользователь пытается получить доступ к представлению? ВозвращаетHttpResponseRedirect
кsettings.LOGIN_URL
.
Рассмотрим этот код JavaScript, который вызывает представление:
var getPage = function(pageNumber) {
$.ajax({
url: "/list_items/" + pageNumber + "/",
success: function(data) {
$("#list_container").html(formatData(data))
}
});
};
предполагатьsettings.SESSION_COOKIE_AGE = 60
секунд.
Если пользователь переходит на страницу 1, читает ее в течение 61 секунды, а затем нажимает кнопку для страницы 2, Djangologin_required
декоратор обнаружит, что сеанс больше не активен, и вернетHttpResponseRedirect(settings.LOGIN_URL)
, который вызоветsuccess
обратный вызов для получения страницы входа в HTML вместо списка в кодировке JSON.
Вот где это происходит.
Это называетсяuser_passes_test
Вот.
Какой лучший способ справиться с этим?
Вот несколько вещей, о которых я подумал:
1.
success
Обратный вызов должен проверить ответ и посмотреть, получит ли он страницу входа любым способом (проверить, является ли тип содержимого html, проверить содержимое и т. д.). Но это означает, что мы должны обернуть все вызовы AJAX оболочкой обратного вызова следующим образом:
$.ajax({
url: "/list_items/" + pageNumber + "/",
success: sessionExpiryCallbackWrapper(function(data) {
$("#list_container").html(formatData(data))
})
});
Но это ужасно, и разработчики могут забыть сделать это везде.
2.
использование$.ajaxComplete
обрабатывать все запросы.
$.ajaxComplete(globalCompleteCallback);
$.ajax({
success: successCallback,
complete: completeCallback
});
Но это порядок звонков:
successCallback(); // success is called before complete
completeCallback();
globalCompleteCallback(); // this is called after the local callback
Таким образом, мы получаем переадресацию только после сбоя successCallback и, возможно, с ошибками JS из-за неверных данных, которые он получил.
3.
Еслиlogin_required
вернет 403 на запросы AJAX:
if not user.is_authenticated():
if request.is_ajax():
# send 403 to ajax calls
return HttpResponse403("you are not logged in")
else:
# regular code path
return HttpResponseRedirect(settings.LOGIN_URL)
Ноlogin_required
просто используетuser_passes_test
который не делает этого.
user_passes_test
там много функциональности, так что переопределять его не очень хорошая идея.
Какой лучший способ справиться с таймаутами для вызовов AJAX?