Тип содержимого ответа отличается от ожидаемого

У меня есть виджет календаря jquery, который запрашивает несколько источников событий на сервере, и все эти источники возвращают одинаковые ответы в формате JSON.

Что действительно раздражает, так это то, что когда срок действия файла cookie пользователя истекает, все эти источники перенаправляют пользователя на страницу входа, возвращающую содержимое HTML.

Я посмотрел на запрос с помощью fiddler и вижу два выполненных запроса: первый - это запрос от объекта календаря jquery для обновления событий с http-статусом 302 и сразу после запроса на страницу входа с http-статусом 200.

GET /xyz/Adempimenti/GetEvents?_=1289170335910&start=1288566000&end=1291590000 HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Accept: application/json, text/javascript, */*; q=0.01

HTTP/1.1 302 Found
Cache-Control: private
Content-Type: text/html; charset=utf-8
Location: /xyz/Login/LogOn?ReturnUrl=%2fxyz%2fAdempimenti%2fGetEvents%3f_%3d1289170335910%26start%3d1288566000%26end%3d1291590000&_=1289170335910&start=1288566000&end=1291590000

Мой сайт основан на AJAX-вызовах, и этот календарь является лишь примером, объясняющим проблему, с которой я сталкиваюсь. Я хотел бы избежать обработки ошибки при каждом вызове ajax и сделать перенаправление. Оптимальным способом было бы найти способ автоматического отключения пользователя, когда истекает срок его сеансового cookie. Я видел, как это реализовано в некоторой системе электронной почты, которая автоматически создает диалог, сообщающий, что сеанс истек.

Любая помощь в этом направлении?

2 ответа

Решение

Когда jQuery выполняет AJAX-запрос, он отправляет HTTP_X_REQUESTED_WITH заголовок.

Рассматривали ли вы проверку этого заголовка на стороне сервера? Если время сеанса истекло, вместо перенаправления на страницу входа можно вернуть структуру JSON, содержащую сообщение об ошибке "Пожалуйста, войдите в систему".

Это был бы самый чистый метод в моих глазах.

Другой идеей было бы сделать дополнительный Ajax-запрос перед выполнением "настоящего". Если первый запрос не удается или получает text/html Тип контента обратно, вы знаете, что вы больше не вошли в систему. Не очень элегантно, но проще, чем пытаться подсчитать продолжительность сеанса на стороне клиента (что неизбежно будет ненадежным).

Я полагаю, что вы имеете дело с сеансом, информация о тайм-ауте которого хранится на стороне сервера (клиент не обязательно знает, когда его сеанс больше не будет действительным). Получите эту информацию и отправьте ее клиенту вместе с запросом. Простой setTimeout(notifySessionExpiration, sessTimeout * 1000) сделает свое дело.

Чтобы ответить на второстепенные вопросы:

$ajax = isset($_SERVER['HTTP_X_REQUESTED_WITH']) && 
($_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest')

Будет устанавливать $ajax Значение true, если вы имеете дело с запросом XML, предполагая, что браузер отправляет совместимые заголовки (что он обычно делает в наши дни).

Вы, вероятно, захотите изолировать часть своего кода, которая отправляет 302 (возможно, контроллер всего приложения, который обрабатывает выборку личной информации пользователя на основе сеанса) и собрать исключение, если $ajax правда. Вы, вероятно, захотите отправить обратно 401 или 403, а затем сделать так, чтобы ваш обратный вызов Javascript отвечал на этот статус определенным образом (например, перенаправляя на страницу входа или предоставляя всплывающее наложение входа Ajax).

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

  • Не используйте семантически вводящий в заблуждение детектор XHR: по моему мнению, доставка разного контента разным запрашивающим вполне разумна, если это однотипный контент с определенными адаптациями для запрашивающего (например, причуды браузера). Но когда конкретный запросчик выполняет принципиально другую функциональную роль (например, когда XHR отправляется в ожидании ответа JSON/XML по сравнению с тем, когда браузер отправляет обычный HTTP-запрос для HTML), тогда запрос не должен быть для тот же актив. На мой взгляд, лучшая практика - создавать HTML для .html или пути без расширения, например GET /mypage.html или же GET /mypageв то время как XHR-ориентированное содержимое должно быть GET /mypage.json или же GET /mypage.xml природа. Это не значит, что XHR никогда не должен получать HTML-ответ. Иногда это совершенно уместно, например, когда вы загружаете фрагмент HTML для формы входа в систему или просто используете AJAX для переходов страниц.
  • Внедрите систему, чтобы поддерживать ваш сеанс в действии: если вы хотите, чтобы ваш сеанс истекал только по времени, а не только до тех пор, пока браузер не будет закрыт, а затем выполните вызов на стороне клиента, чтобы обновить сеанс простым AJAX-запросом до его истечения (если страница закрыта, запрос не запускается, что позволяет сеансу истечь по истечении выделенного времени).
Другие вопросы по тегам