AJAX и проблемы с кодировкой

Вот уже полтора года в draft-ах пылился пост о надуманности проблем с кодировками и т.н. AJAX-ом.
Каждый раз, когда на форумах всплывали вопросы подобного характера, хотелось дать ссылку, на всякий всплеск заходов на блог по запросам “кодировка, ajax, проблема” хотелось его опубликовать, но мне казалось, что пост ещё не закончен, надо ещё чуть-чуть дописать…
Но вот буквально сегодня появился удивительно похожий пост – ajax, cp1251. Похожий по содержанию, но совершенно противоположный по смыслу.
Посему свой черновичок я решил удалить, а поведать свою “истину” в форме критики совета fxposter-а.

Ни для кого ни секрет, что кодировкой получаемых через Ajax данных по-умолчанию принимается UTF-8.

На самом деле это секрет. Для многих секрет. И многие не понимают почему это так.
Внутреннее представление строк (и регулярных выражений) в JavaScript для всех не-ASCII последовательностей как раз UTF-8.
Отсюда и проистекает т.н. “проблема” – если кодировка не указана явно и используется нелатиница, она будет интерпретирована как utf-8 последовательность.

Update 29.11 Свежий воздух и Давид Мзареулян остудили пыл, поэтому спешу уточнить о чём именно будет идти речь ниже.
Итак – у вас есть некий ресурс в однобайтовой кодировке (к гадалке не ходи это будет windows-1251) и вы озаботились освоить новый buzzword по имени AJAX. Немного почитав, вы делаете первые робкие шаги в этом направлении и тут же наступаете на “детские грабли”, а затем, немного отдышавшись, мчитесь на форумы с криком о помощи. И вам эту помощь окажут – переделай мол, свой ресурс на utf-8… Конечно-конечно скажете вы и пойдёте переделывать…
Я же хочу остеречь от таких опрометчивых шагов.

Cтандартное решение, которое наперебой советуют все – “используй utf-8 и нет проблем”.

И советчики правы – проблем действительно не будет.

Просто трафик увеличится “вдвое”. Те же данные, тот же результат, а трафика “в два раза” больше. Ага?

Что вы там говорите насчёт порошка?!?

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

  • Первое, оно же главное – ВСЕГДА указывайте кодировку контента. В любом ответе сервера с текстовым контентом обязан быть заголовок Content-Type: your/type; charset=your-charset.
    Дешевле всего это сделать, настроив сервер (например в php через default_charset)
  • Указывайте charset при включении javascript в тело документа (<script type="text/javascript" charset="your-charset"> )
  • Указывайте ПРАВИЛЬНЫЙ charset

    предварительно установив соответствующий заголовок – “Content-Type: text/html; charset=cp1251″

    В данном конкретном взятом за жопу случае fxposter сам себе злобный буратина.

    Any registered IANA charset may be used, but UTF-8 is preferred.

    Ну нету среди any registered кодировки с названием cp1251…

Для полноты картины приведу пару проблемных моментов, с которыми столкнуться прийдётся:

  • Не позволяйте AJAX-ответам, которые содержат “нелатиницу” оставаться в кеше браузера (при 304 Not Modified ответ поднимется из кеша, но в качестве charset “некоторые браузеры” используют utf-8)
  • JSON text SHALL be encoded in Unicode. The default encoding is UTF-8.

    Этим правилом НАГЛО пользуются производители различных библиотек для json_[en|de]code, но браузерам (как мы выяснили ранее) главное кодировку указать, а там всё разрулится.
    Отсюда и “проблема” – кодировать данные в JSON нужно вручную, распространнёные библиотечные функции на входе ожидают utf-8.

Мораль сей басни я жду от вас в комментариях.

28.11.08  
MiRacLe
 |  ,  | RSS с комментариями  | trackback url
28.11.08 21:45 |  comment от Давид Мзареулян

Используйте gzip-сжатие и проблем снова не будет.

28.11.08 23:03 |  comment от conf

Имхо не стоят все эти проблемы экономии трафика, да и правильно выше уже про gzip посоветовали. Плюс проблем больше, если у вас база и серверный код тоже в юникоде :)

29.11.08 00:21 |  comment от GolDen

IMHO очень сложно получается, много “но” при сомнительных выгодах по трафику, мой выбор UTF-8. А проблему трафика, лучше решать кэшированием или как правильно указал предыдущий комментатор с помощью gzip-сжатия. Например, этот сайт также отображается в кодировке UTF-8, и, не смотря на его явную одно-язычную направленность, автора это почему-то не беспокоит ;)

29.11.08 01:20 |  comment от MiRacLe

Это конечно отлично – ваша база в unicode, код в unicode – вообще непонятно зачем вы прочитали эту чудо{вищную} заметку – я просил вас на полдороги прекратить чтение и идти поддерживать свой проект дальше…

Этот сайт (к моему стыду) имеет 2-3 килозахода в месяц и трафик им создаваемый поистине смешон…

Но если ваш проект имеет 2-3 килохита в минуту “сомнитильная выгода” выливается в килобаксы, что уже, согласитесь, не кисло…

29.11.08 01:58 |  comment от Давид Мзареулян

Вот у Вас лично выливается лишний трафик в килобаксы хоть где-нибудь? Я, например, сейчас был бы счастлив отдавать со своего сайта _больше_ трафика, потому что иначе я не вписываюсь в бесплатные соотношения. К сожалению или к счастью, но ни на ajax-е ни на html-контенте заметного выигрыша трафика (в любую сторону) получить невозможно. Картинки и прочая медиа покрывает всё это как бык овцу.

Блин, 2008-ой год на дворе, а вы всё создаёте себе проблемы с кодировками и мужественно их потом преодолеваете…

29.11.08 02:03 |  comment от MiRacLe

Вот 2008-ой на дворе, а у меня база, и куча приложений, работающих с ней, в кодировке windows-1251 – найти бы мне хотя бы ОДНУ причину выставлять эту базу в вебе через UTF-8…

29.11.08 02:05 |  comment от MiRacLe

И да, у меня проекты на 90 с гаком процентов текстовые…

29.11.08 02:18 |  comment от Давид Мзареулян

У меня тоже есть старый сайт в 1251. И даже до сих пор живёт один проект в КОИ-8 (и немаленький, кстати). Но мне и в голову не придёт описывать какие-то кодировочные решения, применённые в них, потому что я прекрасно понимаю, что это всё — технологии прошлого века, и они должны остаться там.

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

Лет пять уже делаю всё исключительно в utf-8 и вообще никогда на клиентском уровне (оговорка потому что в php, сами знаете, тонкости с юникодом есть) никаких проблем не имел. Чего и всем желаю. А то что у меня остались однобайтовые проекты — так это мои проблемы.

29.11.08 09:54 |  comment от MiRacLe

Ну если юные кулхацкеры, простите, идиоты, то они и без этой “статьи” найдут где нахвататься…
Я-то пишу не “давайте вернёмся в charset-hell (ц)”, а “не горячитесь перелопачивать всё что нажито непосильным трудом, только потому что в IE кракозябры”, т.к. такие советы считаю полным абсурдом…

29.11.08 17:08 |  comment от Давид Мзареулян

Тога следует как-то получше сформулировать задачу. Я лично не понял, что в начальных условиях у нас однобайтовый сайт, передалка которого обойдётся себе дороже. Напротив, пассаж:

Cтандартное решение, которое наперебой советуют все – “используй utf-8 и нет проблем”.

И советчики правы – проблем действительно не будет.

Просто трафик увеличится “вдвое”. Те же данные, тот же результат, а трафика “в два раза” больше. Ага?

Что вы там говорите насчёт порошка?!?

Если вам этот фактор кажется мало***щим, то на этом чтение надо прекратить и начать переделывать свой проект на использование UTF-X

лично я расшифровал как «вы конечно можете делать проекты на utf, если вам не жалко трафика, а вот если вы думаете о юзере…»

29.11.08 17:08 |  comment от Давид Мзареулян

Прошу прощения за опечатки.

29.11.08 17:51 |  comment от MiRacLe

Вставил небольшой update. Спасибо за участие :)

25.10.09 06:51 |  comment от mascik

интресно интересно…
однако
//Проверяем все ли переменные на месте
if (!(isset($_GET['name']) &&
isset($_GET['telefon']) &&
isset($_GET['interes']) &&
isset($_GET['time']))) {die(‘Ошибка в данных!’);}
//Строим тело и загаловки
$message .= ‘Имя: ‘.$name.”;
$message .= ‘Номер телефона: ‘.$telefon.”;
$message .= ‘Что интересует: ‘.$interes.”;
$message .= ‘Желаемое время звонка: ‘.$time.”;
$message .= ‘Дата подачи заявки: ‘.$now;
echo ‘В результате тут будет шляпа которая не работает в Opera UTF ‘
приходится делать перекодировку ..поэтому все
зависит от средств реализации..
вообщем UTF круто..но не настолько чтобы его везде сувать….и не в многозычные системы вообще смысла нету его ставить…лишняя нагрузка работы с двухбайтными символами= эквивалентная 20%…

25.10.09 09:17 |  comment от MiRacLe

Конечно глупо переспрашивать, но тем не менее всё-таки любопытно что вы хотели сказать этой ахи^W хм… этим кодом? Что у вас там не работает? Где? При каких обстоятельствах? Как вообще всё это соотносится с описанной темой?

Есть возможность прокомментировать ситуацию

WP не сожрёт только эти тэги: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>