Как правильно кодировать символы Unicode в URL?

Я знаю нестандартную схему% 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'

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

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

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

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

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

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

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

что имеет смысл, поскольку ... не может быть закодирован с помощью Latin-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.

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


person Josh Gibson    schedule 26.05.2009    source источник
comment
Оба ваших примера закодированы как UTF-8. Первый, конечно, не Latin-1, учитывая его длину в три байта ...   -  person Jakob Borg    schedule 14.04.2010
comment
% E2% 99% A5 шестнадцатеричный для значений байтов костюм черного сердца в UTF-8. Это черное сердце не является частью набора символов Latin-1.   -  person Hawkeye Parker    schedule 16.01.2015
comment
Чтобы точно узнать, как и что кодирует браузер (и много другой полезной информации), используйте инструменты разработчика, встроенные в большинство современных браузеров, или получите бесплатный отладчик HTTP, например Fiddler.   -  person Hawkeye Parker    schedule 16.01.2015


Ответы (5)


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

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

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

person John Biesnecker    schedule 27.05.2009
comment
Также следует использовать UTF-8, потому что это единственная кодировка, разрешенная новым стандартом IRI (RFC 3987, инструменты .ietf.org / html / rfc3986), который заменяет старый стандарт URL. - person Remy Lebeau; 14.08.2009
comment
На случай, если другие будут так же удивлены, как и я, текст в комментарии @ RemyLebeau упоминает RFC3987, но ссылка ведет на более старую спецификацию 3896. Правильный URL-адрес, очевидно, tools.ietf.org/html/rfc3987 - person tripleee; 14.03.2014
comment
Да, извините за это. URI определяется RFC 3986, IRI определяется RFC 3987. - person Remy Lebeau; 14.03.2014

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

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

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

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

person araqnid    schedule 27.05.2009
comment
RFC 3987 (tools.ietf.org/html/rfc3986) определяет стандартную кодировку - UTF- 8 должен использоваться при кодировании символов, которые иначе не могут быть закодированы. - person Remy Lebeau; 14.08.2009

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

person Remy Lebeau    schedule 19.06.2009
comment
Я хочу увидеть обновление протоколов, чтобы Unicode полностью поддерживался в URL-адресах, а не только через процентное кодирование. - person Mathieu J.; 29.06.2015
comment
IRI допускает использование некодированных символов Unicode, за исключением тех немногих случаев, когда необходимо кодировать зарезервированные символы. - person Remy Lebeau; 29.06.2015

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

Вместо этого вы указываете IRI, и он преобразуется в URI при подключении к сети.

person Mark Nottingham    schedule 14.04.2010

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

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

person Pat O    schedule 27.05.2009