Странности с поведением браузеров в кодировке get-параметров (Windows-1251 / UTF-8)

Привет,

Есть локальная машинка, на которой пишется и отлаживается всякое разное, преимущественно на PHP. Обнаружил странное (не сказать — неприятное) поведение разных браузеров при кодировании запроса.

Вот тестовый файлик:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Превед</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
<p>
<?php
    echo '<strong>'.$_GET['param'].'</strong><br />';
    echo $_SERVER['HTTP_USER_AGENT'].'<br />';
    echo $_SERVER['HTTP_ACCEPT_CHARSET'].'<br />';
?>
</p>
</body>
</html>


* This source code was highlighted with Source Code Highlighter.



А вот, что любопытно, результат:
image

Вот — firebug с ответом сервера:

HTTP/1.1 200 OK
Date: Sun, 22 Jan 2012 22:02:57 GMT
Server: Apache/2.2.20 (Win32) PHP/5.2.17
X-Powered-By: PHP/5.2.17
Content-Length: 467
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html; charset=UTF-8


Как видно, UTF-8 в запросе передает только Chrome (я не менял никаких настроек в браузерах). Все остальные начинают нормально отображать введенную кириллицу только при явном переключении браузера на Win-1251.

Меня несколько смущает такое поведение, причем, в основном тем, что я не могу понять — то ли надо больше спать и меньше писать руками в адресной строке, то ли все же что-то надо исправлять :)

Больше всего напрягает то, что в реальном проекте определить кодировку входных данных весьма непросто (вот тут тема раскрыта очень хорошо). Еще несколько непонятен тот факт, что те же браузеры к википедии, например, абсолютно корректно все передают.
Что и где неправильно?
23 января в 02:17
Cyrill 35,9

отсортировано по дате по оценке
ответы (6)

+3
homm #
Не пишите руками в адресной строке. Так как достоверных источников информации нет, браузеры считают что руки у вас в кодировке win-1251.
ru.wikipedia.org/wiki/Ложка Введите это руками в адресной строке. Все браузеры как-то вдруг начинают понимать что руки у Вас превратятся в utf-8. taliban, 23 января в 13:42
самую суть ухватил. в какой момент браузер начинает считать, что в википедию все надо передавать в Utf-8? Cyrill, 23 января в 17:44
–1
himik #
в начале страницы
<?php header("Content-Type: content=text/html; charset=utf-8"); ?>
нет:
1. жирным выделил то, что вообще php выключает: («Content-Type: content=text/html; charset=utf-8»);
2. есть meta
3. сервер и без заголовков отдает правильный content-type (см. вывод firebug).
Cyrill, 23 января в 02:34
Сервер тут вообще не при чём, потому что браузер сначала преобразовывает русские буквы в коды символов, а только потом делает запрос на сервер WebSpider, 23 января в 02:58
–1
taliban #
Денвер стоит?
Если да, проверьте это firsthand.ru/node/4 taliban, 23 января в 02:42
Не денвер, руками ставил. БД в примере не используется, GD подключен, mbstring — тоже. Cyrill, 23 января в 02:48
Просто на всякий случай проверьте есть ли строка «default-character-set = utf8» и если нет, добавьте =) Не утверждаю что в этом причина, но все возможно. Опера прекрасно дружит с utf-8, поэтому подозреваю проблему в сервере. taliban, 23 января в 03:18
AddDefaultCharset с этим перепутал taliban, 23 января в 03:30
+3
WebSpider #
то ли надо больше спать и меньше писать руками в адресной строке

Абсолютно верно, особенно насчёт второго пункта :)

Из скриншота с фф отлично видно, что слово «превед» в get-параметре у вас передано в кодировке windows-1251, поэтому и выводится оно некорректно на странице с кодировкой utf-8.

В википедии же ссылка выглядит так: ru.wikipedia.org/wiki/%D0%9F%D1%80%D0%B5%D0%B2%D0%B5%D0%B4

Соответственно, если вы передадите такой же get-параметр — везде всё будет работать как надо:
autoref.local/test.php?param=test%20%D0%9F%D1%80%D0%B5%D0%B2%D0%B5%D0%B4
Или вопрос был в том почему все браузеры кроме хрома восприняли сконвертировали кириллицу в win1251? WebSpider, 23 января в 02:57
1251 на глаз? Круто. По сути вопроса — да, пожалуй, вопрос конвертирования меня и напрягает — я не могу понять почему запрос к моей тестовой страничке конвертируется, а к википедии — нет? Cyrill, 23 января в 03:01
а вы запрос в википедию руками писали или ссылкой со страницы? сделайте html-страницу в кодировке utf-8, и разместите на ней ссылку вида <a href="http://autoref.local/test.php?param=test превед">нажми меня</a> и, уверен, всё заработает как надо, потому что кодировка уже будет изначально выставлена правильно WebSpider, 23 января в 03:04
Везде — руками в адресной строке. Скрипт — utf-8 (см. Title на скрине). Со ссылками как раз вопросов нету, непонятно по какому принципу происходит преобразование запроса к странице, которая отдается в utf. Cyrill, 23 января в 03:12
Да при чём здесь страница вообще? Адрес преобразовывается до отправки запроса WebSpider, 23 января в 03:14
Я, кажется, понял, как запросы отличать :) Cyrill, 23 января в 03:15
В общем, ответ на ваш вопрос такой: фф (и др.) кодирует параметры query string как windows-1251, а url-параметры как utf-8. хром же все как utf-8 WebSpider, 23 января в 03:17
Да при чём здесь страница вообще? Адрес преобразовывается до отправки запроса

Как тогда быть с wikipedia? (коммент с вопросом).
Cyrill, 23 января в 17:45
Внимательнее читайте мой комментарий выше. В википедии параметр передаётся в url, а в вашем скрипте — как параметр query string. Вот и вся разница, и википедия тут не при чём WebSpider, 23 января в 20:17
попробуйте в википедию передать параметр wikipedia.org/?param=превед, и вы увидите, что он будет закодирован так же как и ваш (в win1251). Я уже не знаю как понятнее это объяснить :) WebSpider, 23 января в 20:20


Тепер осознал, вопрос снимается. Возникает следующий: чем они точно определяют кодировку входящего запроса?)
Cyrill, 23 января в 20:28
Сложно сказать, видимо чем-то наподобие того, на что у вас ссылка в вопросе :) WebSpider, 23 января в 21:10
0
VolCh #
В Файерфоксе параметр явно закодирован не в Utf-8. Должно быть ?param=test%20test=%D0%BF%D1%80%D0%B5%D0%B2%D0%B5%D0%B4. Чем кодировали?
то есть param=test%20%D0%BF%D1%80%D0%B5%D0%B2%D0%B5%D0%B4 :) VolCh, 23 января в 03:03
Руками писал в адресной строке :) Cyrill, 23 января в 03:13
0
MTonly #
Не используйте GET-параметры с нелатинскими символами. Используйте чистые URL-адреса («ЧПУ») вида «/раздел/подраздел/» — основную часть URL-адреса все распространённые браузеры уже давно отправляют в кодировке UTF-8.

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.