Тип содержимого ответа отличается от ожидаемого - PullRequest
2 голосов
/ 08 ноября 2010

У меня есть виджет календаря 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 ]

4 голосов
/ 08 ноября 2010

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

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

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

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

1 голос
/ 08 ноября 2010

Я полагаю, что вы имеете дело с сеансом, информация о тайм-ауте которого хранится на стороне сервера (клиент не обязательно знает, когда его сеанс больше не будет действительным).Получите эту информацию и отправьте ее клиенту вместе с запросом.Простой 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-запросом до его истечения (если страница закрыта,запрос не запускается, что позволяет сеансу истечь по истечении выделенного времени).
...