Как правильно 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.

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

5 ответов

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

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

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

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

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

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

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

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

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

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

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

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

Другие вопросы по тегам