Каков правильный способ кодирования URL-символов Unicode?

Я знаю о нестандартной схеме% uxxxx, но это не кажется мудрым выбором, поскольку схема была отвергнута W3C.

Некоторые интересные примеры:

Сердечный персонаж. Если я напечатаю это в своем браузере:

http://www.google.com/search?q=♥

Затем скопируйте и вставьте его, я вижу этот URL

http://www.google.com/search?q=%E2%99%A5

что делает его похожим на Firefox (или Safari).

urllib.quote_plus(x.encode("latin-1"))
'%E2%99%A5'

что имеет смысл, за исключением вещей, которые не могут быть закодированы в латинском-1, как символ тройной точки.

Если я наберу URL

http://www.google.com/search?q=…

в мой браузер, затем скопируйте и вставьте, я получаю

http://www.google.com/search?q=%E2%80%A6

назад. Кажется, что это результат выполнения

urllib.quote_plus(x.encode("utf-8"))

что имеет смысл, поскольку... невозможно закодировать с помощью латинского-1.

Но тогда неясно, как браузер знает, следует ли декодировать UTF-8 или Latin-1.

Так как это кажется неоднозначным:

In [67]: u"…".encode('utf-8').decode('latin-1')
Out[67]: u'\xc3\xa2\xc2\x80\xc2\xa6'

работает, поэтому я не знаю, как браузер определяет, следует ли декодировать это с помощью UTF-8 или Latin-1.

Какая правильная вещь для специальных символов, с которыми мне нужно иметь дело?

Ответ 1

Я всегда кодировал бы в UTF-8. На странице в Википедии на процентное кодирование:

Общий синтаксис URI предусматривает, что новые схемы URI, которые обеспечивают представление символьных данных в URI, должны, по сути, представлять символы из незарезервированного набора без перевода и должны преобразовывать все остальные символы в байты в соответствии с UTF-8, а затем процентное кодирование этих значений. Это требование было введено в январе 2005 года с публикацией RFC 3986. Схемы URI, введенные до этой даты, не затрагиваются.

Похоже, что в прошлом были другие способы использования кодирования URL-адресов, браузеры пытались использовать несколько методов декодирования URI, но если вы делаете кодировку, вы должны использовать UTF-8.

Ответ 2

Как правило, правило состоит в том, что браузеры кодируют ответы формы в соответствии с типом содержимого страницы, с которой была подана форма. Предполагается, что если сервер отправит нам "text/xml; charset = iso-8859-1", они ожидают отклики в том же формате.

Если вы просто вводите URL-адрес в строке URL-адреса, тогда браузер не имеет базовой страницы для работы и, следовательно, просто должен угадать. Таким образом, в этом случае, кажется, все время работает utf-8 (так как оба входа генерируют значения трехоктетной формы).

Печальная истина заключается в том, что в AFAIK нет стандарта для того, какой символ задает значения в строке запроса или даже любые символы в URL-адресе, следует интерпретировать как. По крайней мере, в случае значений в строке запроса нет оснований полагать, что они обязательно соответствуют символам.

Известная проблема заключается в том, что вы должны сообщить своей структуре сервера, какой символ вы ожидаете, что строка запроса будет закодирована как, например, в Tomcat, вам нужно вызвать request.setEncoding() (или какой-либо аналогичный метод ) перед вызовом любого из методов request.getParameter(). Недостаток документации по этому вопросу, вероятно, отражает недостаточную осведомленность о проблеме среди многих разработчиков. (Я регулярно спрашиваю у собеседников Java, какая разница между Reader и InputStream, и регулярно получает пустые взгляды)

Ответ 3

IRI (RFC 3987) является последним стандартом, который заменяет URI/URL (RFC 3986 и старше). URI/URL-адрес не поддерживают Unicode (ну, RFC 3986 добавляет положения для будущих протоколов URI/URL-адресов для поддержки, но не обновляет прошлые RFC). Схема "% uXXXX" является нестандартным расширением, позволяющим Unicode в некоторых ситуациях, но не универсально реализовано всеми. IRI, с другой стороны, полностью поддерживает Unicode и требует, чтобы текст кодировался как UTF-8, а затем был закодирован в процентах.

Ответ 4

IRI не заменяют URI, потому что разрешены только URI (эффективно, ASCII) в некоторых контекстах, включая HTTP.

Вместо этого вы указываете IRI и преобразуетесь в URI при выходе на провод.

Ответ 5

Первый вопрос - каковы ваши потребности? Кодировка UTF-8 - довольно хороший компромисс между принятием текста, созданного с помощью дешевого редактора, и поддержкой широкого спектра языков. Что касается браузера, определяющего кодировку, ответ (с веб-сервера) должен указать браузеру кодировку. Тем не менее большинство браузеров попытаются угадать, потому что во многих случаях это либо отсутствует, либо неверно. Они угадывают, читая некоторую часть потока результатов, чтобы увидеть, есть ли символ, который не соответствует кодировке по умолчанию. В настоящее время все браузеры (? Я не проверял это, но это довольно близко к true) используют utf-8 как значение по умолчанию.

Так что используйте utf-8, если у вас нет веской причины использовать одну из многих других схем кодирования.