Я недавно писал про то, как мы используем заголовок Accept для определения, в каком виде присылать HTTP-ответ: структуру для ajax-функции или страницу целиком. Через некоторое время мы напали на некоторые баги, каковой историей и хочу поделиться.
Баги в порядке появления такие:
Опера вместо установки заголовка в желаемое значение добавляет его к своей дефолтной строке, в результате чего получается что-то вроде
Accept: application/xml, text/html, application/xml;q=0.9 ...
Соответственно, проверки типа
if accept == 'application/xml'
не работалиПосле этого мы прикутили библиотечку Джо Грегорио mimeparse, которая умеет парсить Accept с поиском наиболее подходящего типа из указанного списка. Надежда была на то, что
best_match(AJAX_TYPES, accept)
будет выдавать один из AJAX_TYPES только если он реально присутствует в строке. Это решение убил IE6, который по некоторой неопределенной закономерности для обычных (не-ajax) запросов может прислать просто
*/*
, что означает "да, я конечно принимаю ajax'овый ответ (и любой другой, гы-гы)". В результате ajax'овые XML'ы присылались иногда вместо обычных страниц. Закономерность, повторюсь, выявить не удалось.Еще с best_match плохо работает Firefox, потому что в его стандартной строке присутствует тип
application/xml
, причем с приоритетом, большим чем уtext/html
. Поэтому если парсить вот так честно, то Firefox предпочитает вместо обычных страниц ajax'овые ответы, которые мы присылаем в видеapplication/xml
в том числе.
В итоге, победить эту мешанину получилось тем, что:
- мы заменили простой
application/xml
на более специфичныйapplication/xml+ajax
- мы всегда ищем содержание нужного типа в Accept в явном виде
А в целом, это все оставляет некий неприятный осадок, потому что используй мы "некошерный" подход с ?ajax=1
, проблем бы не возникло. Так что приходится оставить использование Accept только на те случаи, где клиентами выступают не браузеры, а специально написанные клиенты, которые точно контроллируют свои заголовки, и точно знают, что хотят получить. Как например у Джеймса Беннетта для определения запроса yadis-документа с главной страницы.
Комментарии: 15
Тоже столкнулся с теми же проблемами, и практически так же решил - либо это собственный заголовок (x-requested-with), либо свой экзотичный mime-type(text/x-ajax) или крайний случай - та самая переменная в запросе:
$respond_to_ajax = ((isset($_SERVER['HTTP_X_REQUESTED_WITH']) &&