URL, кодирующий пробел: + или%20?

Когда пробел в URL закодирован +и когда это закодировано в %20?

6 ответов

Решение

Из Википедии (выделение и ссылка добавлены):

Когда данные, введенные в формы HTML, отправляются, имена и значения полей формы кодируются и отправляются на сервер в сообщении HTTP-запроса с использованием метода GET или POST или, исторически, по электронной почте. Используемая по умолчанию кодировка основана на очень ранней версии общих правил процентного кодирования URI с рядом модификаций, таких как нормализация новой строки и замена пробелов на "+" вместо "%20". Данные MIME-типа, закодированные таким образом, имеют вид application/x-www-form-urlencoded, и в настоящее время они определены (все еще очень устаревшим образом) в спецификациях HTML и XForms.

Таким образом, реальный процент использует кодирование %20 в то время как данные формы в URL находятся в измененной форме, которая использует +, Так что вы, скорее всего, увидите только + в URL в строке запроса после ?,

Эта путаница объясняется тем, что URL до сих пор "сломан".

Возьмите, например, http://www.google.com/. Это URL. URL-адрес - это унифицированный указатель ресурса и на самом деле указатель на веб-страницу (в большинстве случаев). URL-адреса на самом деле имеют очень четкую структуру со времени первой спецификации в 1994 году.

Мы можем извлечь подробную информацию об URL-адресе " http://www.google.com/ ":

+---------------+-------------------+   
|      Part     |      Data         |   
+---------------+-------------------+   
|  Scheme       | http              |   
|  Host         | www.google.com    |   
+---------------+-------------------+  

Если мы посмотрим на более сложный URL, такой как:

" https://bob:bobby@www.lunatech.com:8080/file;p=1?q=2 "

мы можем извлечь следующую информацию:

+-------------------+---------------------+
|        Part       |       Data          |
+-------------------+---------------------+
|  Scheme           | https               |
|  User             | bob                 |
|  Password         | bobby               |
|  Host             | www.lunatech.com    |
|  Port             | 8080                |
|  Path             | /file;p=1           |
|  Path parameter   | p=1                 |
|  Query            | q=2                 |
|  Fragment         | third               |
+-------------------+---------------------+

https://bob:bobby@www.lunatech.com:8080/file;p=1?q=2#third
\___/   \_/ \___/ \______________/ \__/\_______/ \_/ \___/
  |      |    |          |          |      | \_/  |    |
Scheme User Password    Host       Port  Path |   | Fragment
        \_____________________________/       | Query
                       |               Path parameter
                   Authority

Зарезервированные символы различны для каждой части.

Для HTTP-URL-адресов пробел в части фрагмента пути должен быть закодирован как "%20" (не совсем, не "+"), в то время как символ "+" в части фрагмента пути может быть оставлен незакодированным.

Теперь в части запроса пробелы могут быть закодированы либо в "+" (для обратной совместимости: не пытайтесь искать его в стандарте URI), либо в "% 20", пока символ "+" (в результате этой неоднозначности) должен быть экранирован до "%2B".

Это означает, что строка "синий + голубой" должна кодироваться по-разному в частях пути и запроса:

" http://example.com/blue+light%20blue?blue%2Blight+blue ".

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

То, к чему это сводится, является:

У тебя должно быть %20 перед ? а также + после.

Источник

Пробел может быть закодирован только в "+" в части запроса "пары ключ-значение контента" типа application/x-www-form-urlencoded части URL. Это МОЖЕТ, а НЕ ДОЛЖНО. В остальных URL он закодирован как%20.

На мой взгляд, лучше всегда кодировать пробелы как%20, а не как "+", даже в части запроса URL, потому что это спецификация HTML (RFC-1866), которая указывает, что символы пробела должны кодироваться как "+" in "application/x-www-form-urlencoded"пары ключ-значение типа содержимого. (см. параграф 8.2.1. подпункт 1.) Этот способ кодирования данных формы также приведен в более поздних спецификациях HTML, например, ищите соответствующие параграфы о application/x-www-form-urlencoded в спецификации HTML 4.01 и т. д.,

Вот пример строки в URL, где спецификация HTML допускает кодирование пробелов в виде плюсов: " http://example.com/over/there?name=foo+bar". Таким образом, только после "?", Пробелы могут быть заменены на плюсы, в соответствии со спецификацией HTML. В других случаях пробелы должны быть закодированы в%20. Но так как трудно правильно определить контекст, лучше никогда не кодировать пробелы как "+".

Я бы порекомендовал кодировать в процентах все символы, кроме "незарезервированных", определенных в RFC-3986, с.2.3

unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"

Реализация зависит от языка программирования, который вы выбрали.

Если ваш URL содержит национальные символы, сначала закодируйте их в UTF-8, а затем закодируйте в процентах результат.

Я бы посоветовал %20,

Вы жестко их кодируете?

Это не очень согласованно для разных языков. Если я не ошибаюсь, в PHP urlencode() рассматривает пространства как + в то время как питон urlencode() относится к ним как %20,

РЕДАКТИРОВАТЬ:

Кажется, я ошибаюсь. Питона urlencode() (по крайней мере, в 2.7.2) использует quote_plus() вместо quote() и таким образом кодирует пробелы как "+". Представляется также, что рекомендация W3C - это "+", как указано здесь: http://www.w3.org/TR/html4/interact/forms.html

И на самом деле, вы можете следить за этой интересной дискуссией на собственном трекере проблем Python о том, что использовать для кодирования пространств: http://bugs.python.org/issue13866.

РЕДАКТИРОВАТЬ № 2:

Я понимаю, что наиболее распространенный способ кодирования "" - это "+", но просто примечание, это может быть только я, но я нахожу это немного запутанным:

import urllib
print(urllib.urlencode({' ' : '+ '})

>>> '+=%2B+'

Подводя итог (несколько противоречивым) ответам здесь, я думаю, что их можно свести к следующему:

      | standard      | +   | %20 |
|---------------+-----+-----|
| URL           | no  | yes |
| query string  | yes | yes |
| form params   | yes | no  |
| mailto query  | no  | yes |

Итак, исторически я думаю, что произошло следующее:

  1. RFC определил довольно четкий стандарт формы URL-адресов и того, как они кодируются. В этом контексте запрос представляет собой просто «строку», нет указания, как следует кодировать пары ключ/значение.
  2. Ребята из HTTP разработали стандарт кодирования пар ключ/значение в параметрах формы и заимствовали его из стандарта кодирования URL, за исключением того, что пробелы должны быть закодированы как+.
  3. Веб-парни сказали: круто, у нас есть способ кодировать пары ключ/значение, давайте поместим это в строку запроса URL.

Результат: у нас есть два разных способа кодирования пробелов в URL-адресе в зависимости от того, о какой части вы говорите. Но это даже не нарушает стандарт URL. С точки зрения URL «запрос» — это просто черный ящик. Если вы хотите использовать там другие кодировки, кроме кодировки процентов: выбейте себя.

Но, как показывает пример электронной почты, может быть проблематично заимствовать из реализации form-params строку запроса URL. Таким образом, в конечном итоге использование %20 безопаснее, но для него может не быть готовой поддержки библиотеки.

Поскольку я был удивлен, что никто не процитировал настоящий RFC 3986 о «процентном кодировании», я добавляю здесь свой собственный ответ:

Поскольку вышеупомянутый RFC не содержит никаких ссылок на пространства кодирования, такие как+, я думаю, используя%20это путь сегодня.

Например, «%20» — это процентная кодировка двоичного октета «00100000» (ABNF: %x20), который в US-ASCII соответствует символу пробела (SP).

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