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

723

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

ДО Н.Э.
источник
2
Этот вопрос был бы более полезным, так как несколько языковых вопросов, верно?
SquareCandy
2
Возможный дубликат Когда кодировать пробел в плюс (+) или% 20?
Пользователь
3
@user вопрос, на который вы ссылаетесь, был задан позже, что делает его обманщиком, а не этим.
Воинственный шимпанзе

Ответы:

425

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

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

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

детеныш
источник
2
Таким образом, + кодирование будет технически кодированием multipart / form-data, в то время как процентное кодирование является application / x-www-form-urlencoded?
до н.э.
17
@BC: нет - multipart/form-dataиспользует кодировку MIME; application/x-www-form-urlencodedиспользует +и правильно закодированные URI %20.
Макдауэлл
8
«Так что вы, скорее всего, увидите только + в URL в строке запроса после?» Это занижение. Вы никогда не должны видеть «+» в части пути URL, потому что он не будет делать то, что вы ожидаете (пробел).
Адам Гент
34
Итак, в основном: цель представления GET - http://www.bing.com/search?q=hello+worldэто ресурс с пробелом в имениhttp://camera.phor.net/cameralife/folders/2012/2012-06%20Pool%20party/
William Entriken
8
Обратите внимание, что для ссылок электронной почты вам нужен% 20, а не + после?. Например, mailto:support@example.org?subject=I%20need%20help. Если вы пробовали это с +, электронное письмо будет открываться с + es вместо пробелов.
Сигморал
288

Эта путаница объясняется тем, что 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до ?и +после.

Источник

Матас Вайткявичюс
источник
>> У тебя должно быть% 20 ​​до? и + после Извините за глупый вопрос. Я немного знаю, что параметр hashtag используется после "?" параметр вопросительного знака. Хотя это как-то отличается, потому что использование "#" не перезагружает страницу. Но я пытался использовать% 20 ​​и знак + после хештега "#", и, похоже, он не работает. Какой из них нужно использовать после "#"?
Philcyb
@Philcyb Вы могли бы хотеть прочитать это en.wikipedia.org/wiki/Percent-encoding
Матас Вайткявичюс
Есть ли у части запроса «официальный» стандарт? Я думал, что в основном эта часть зависит от приложения. 99,99% приложений используют key1=value1&key1=value2там, где ключи и значения кодируются с соблюдением любых правил, encodeURIComponentно AFAIK содержание части запроса полностью на 100% до приложения. В остальном это касается только первой #, официальной кодировки нет.
мужчина
Дублированный ответ на дублированный вопрос! Но хм, хорошо, я сдался на обоих.
Владимир Вуканац
3
Эта маркировка компонентов ASCII эпична.
jsejcksn
25

Я бы порекомендовал %20.

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

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

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

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

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

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

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

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

>>> '+=%2B+'
Руи Виейра
источник
Не жестко. Попытка определить с эстетической точки зрения, как будут выглядеть мои URL, содержащие пробелы.
до н.э.
Привет, я тоже в замешательстве. Когда пользователь отправляет HTML-форму, как форма кодирует пространство? с каким персонажем? Зависит ли браузер от результата?
GMsoF
1
И URLEncoder.encode()метод в Java также конвертирует его +.
рüффп
И тогда возникает вопрос о том, как обрабатывать кодировку в теле запроса POST: «Content-Type: application / x-www-form-urlencoded», где параметры имеют форму «a = b & c = d», но не в URL вообще, просто тело "документа". Они сделали из этой проблемы настоящий беспорядок, и чертовски сложно найти однозначные ответы.
fyngyrz
Perls uri_escape () рассматривает их как% 20
когда-то
16

Пробел может быть закодирован только в «+» в части запроса «пары ключ-значение контента» типа 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 ». Таким образом, только после «?» Пробелы можно заменить на плюсы . В других случаях пробелы должны быть закодированы в% 20. Но так как трудно правильно определить контекст, лучше никогда не кодировать пробелы как «+».

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

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

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

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

Максим Масютин
источник
1
Зачем кому-то беспокоиться о спецификации HTML, если запрашиваемый ресурс не является HTML? Я видел "+" в некоторых веб-API, которые не отвечают HTML, например, вы запрашиваете PDF. Я считаю неправильным, что они не используют "% 20".
Невероятный Янв
@TheincredibleJan, я согласен с тобой. Вот о чем мой ответ.
Максим Масютин
1
@MaximMasiutin Когда ваш ответ говорит: «Это МОЖЕТ, а НЕ ДОЛЖНО», на какую спецификацию вы ссылаетесь? Я изо всех сил пытаюсь найти спецификацию, которая имеет это как май. В w3.org/TR/1999/REC-html401-19991224/interact/… использование «+» (в разделе запросов) находится в разделе «must» спецификации.
JosephH
2
@JosephH - спасибо за вашу заметку. Это мое личное мнение о МАЙ. Я отредактировал пост. Я имел в виду, что спецификация HTML, которую вы указали, определяет «+», но в контексте URL применяются другие правила, которые также разрешают кодировать пробелы как% 20.
Максим Масютин