Если я хочу создать URL с использованием переменной, у меня есть два варианта кодирования строки. urlencode()
и rawurlencode()
.
Каковы именно различия и что является предпочтительным?
php
urlencode
url-encoding
Гари Уиллоуби
источник
источник
rawurlencode
. Вы редко столкнетесь с системой, которая задыхается, когда заданы пробелы, закодированные как%20
, в то время как системы, которые подавляются пробелами, закодированными как,+
являются более распространенными.Ответы:
Это будет зависеть от вашей цели. Если важна совместимость с другими системами, тогда кажется, что стоит использовать rawurlencode. Единственное исключение - устаревшие системы, которые ожидают, что строка запроса будет следовать стилю кодирования формы пробелов, закодированных как + вместо% 20 (в этом случае вам нужен urlencode).
rawurlencode следует RFC 1738 до PHP 5.3.0 и RFC 3986 впоследствии (см. http://us2.php.net/manual/en/function.rawurlencode.php )
Примечание к RFC 3986 против 1738. rawurlencode до php 5.3 кодировал символ тильды (
~
) в соответствии с RFC 1738. Однако, начиная с PHP 5.3, rawurlencode следует RFC 3986, который не требует кодирования символов тильды.urlencode кодирует пробелы как знаки плюс (а не как
%20
в rawurlencode) (см. http://us2.php.net/manual/en/function.urlencode.php )Это соответствует определению для application / x-www-form-urlencoded в RFC 1866 .
Дополнительное чтение:
Вы также можете посмотреть обсуждение по адресу http://bytes.com/groups/php/5624-urlencode-vs-rawurlencode .
Также стоит посмотреть RFC 2396 . RFC 2396 определяет допустимый синтаксис URI. Основная часть, которая нас интересует, - из 3.4 Query Component:
Как вы можете видеть,
+
это зарезервированный символ в строке запроса и, следовательно, должен быть закодирован в соответствии с RFC 3986 (как в rawurlencode).источник
Доказательство есть в исходном коде PHP.
Я проведу вас через быстрый процесс того, как найти подобные вещи самостоятельно в будущем в любое время. Потерпите меня, будет много исходного кода на C, который вы можете просмотреть (я объясняю это). Если вы хотите освежить в памяти C, то хорошее место для начала - наша SO wiki .
Загрузите исходный код (или воспользуйтесь http://lxr.php.net/, чтобы просмотреть его в Интернете), grep для всех файлов имени функции, вы найдете что-то вроде этого:
PHP 5.3.6 (последняя на момент написания статьи) описывает две функции в своем родном коде C в файле url.c .
RawUrlEncode ()
UrlEncode ()
Хорошо, так что здесь отличается?
По сути, они оба вызывают две разные внутренние функции: php_raw_url_encode и php_url_encode
Так что иди ищи эти функции!
Давайте посмотрим на php_raw_url_encode
И, конечно же, php_url_encode:
Прежде чем я двинусь вперёд, EBCDIC - это другой набор символов , похожий на ASCII, но полный конкурент. PHP пытается справиться с обоими. Но в основном это означает, что байт EBCDIC 0x4c байт не
L
в ASCII, это на самом деле<
. Я уверен, что вы видите здесь путаницу.Обе эти функции управляют EBCDIC, если веб-сервер определил его.
Кроме того, они оба используют
hexchars
поиск по типу символов (думаю, тип строки) , чтобы получить некоторые значения, массив описывается так:Кроме того, функции действительно разные, и я собираюсь объяснить их в ASCII и EBCDIC.
Отличия в ASCII:
UrlEncode:
+
знак в выходную строку.isalnum(c)
), а также не и_
,-
или.
символ, то мы выводим%
знак в позицию массива 0, чтобы массив выглядел вhexchars
массив для поиска вos_toascii
массиве ( массив из Apache, который переводит символ в шестнадцатеричный код) для ключаc
(текущий символ), затем мы побитно сдвигаемся вправо на 4, присваиваем это значение символу 1, а позиции 2 мы присваиваем тот же поиск, за исключением того, что преформуем логическое и посмотреть, если значение равно 15 (0xF), и вернуть 1 в этом случае или 0 в противном случае. В конце концов, вы получите что-то закодированное._-.
символов, он выводит именно то, что есть.RAWURLENCODE:
Примечание: многие программисты, вероятно, никогда не видели итерацию цикла for таким образом, это несколько хакерское и не стандартное соглашение, используемое с большинством циклов for, обратите внимание, оно присваивает
x
иy
проверяет выход приlen
достижении 0, а также увеличиваетx
иy
. Я знаю, это не то, что вы ожидаете, но это правильный код.str
._-.
символов, и если это не так, мы делаем почти то же самое назначение, что и с URLENCODE, где он преобразует поиск, однако мы увеличиваем его по-разному, используяy++
вместоto[1]
этого, потому что Струны строятся по-разному, но в конце концов достигают одной и той же цели.\0
байт.Отличия:
\0
байт строке, как это делает RawUrlEncode (это может быть спорным вопросом)Они в основном повторяются по-разному, один присваивает знак + в случае ASCII 20.
Отличия в EBCDIC:
UrlEncode:
0
, за исключением того, что он является.
или-
, или ИЛИ меньше,A
но больше, чем символ9
, ИЛИ большеZ
и меньше,a
но не a_
. ИЛИ больше, чемz
(да, EBCDIC вроде бы запутался в работе). Если он совпадает с любым из них, выполните поиск, аналогичный найденному в версии ASCII (он просто не требует поиска в os_toascii).RAWURLENCODE:
z
, он исключает~
из URL-кодирования.\0
байт к строке перед возвратом.Grand Summary
~
, чего не делает UrlEncode ( это сообщенная проблема ). Стоит отметить, что ASCII и EBCDIC 0x20 являются пробелами.+
, RawUrlEncode делает пробел%20
через поиск в массиве.Отказ от ответственности: я не прикасался к C в течение многих лет, и я не смотрел на EBCDIC действительно очень долгое время. Если я где-то ошибаюсь, дайте мне знать.
Предлагаемые реализации
Исходя из всего этого, rawurlencode - это то, что нужно делать большую часть времени. Как вы видите в ответе Джонатана Фингланда, придерживайтесь его в большинстве случаев. Он имеет дело с современной схемой для компонентов URI, где, как urlencode делает вещи по-старому, где + означает «пробел».
Если вы пытаетесь конвертировать между старым форматом и новыми форматами, убедитесь, что ваш код не искажается и что-то, что является символом +, превращается в пробел путем случайного двойного кодирования или аналогичных сценариев "упс" пространство / 20% / + проблема.
Если вы работаете на более старой системе с более старым программным обеспечением, которое не предпочитает новый формат, придерживайтесь urlencode, однако, я считаю, что% 20 на самом деле будет обратно совместим, как в старом стандартном% 20 работало, просто не было предпочтительным. Дайте ему шанс, если вы готовы играть, дайте нам знать, как это сработало для вас.
По сути, вы должны придерживаться raw, если ваша система EBCDIC действительно не ненавидит вас. Большинство программистов никогда не столкнутся с EBCDIC ни в одной из систем, созданных после 2000 года, может быть, даже 1990 года (это, на мой взгляд, все еще актуально).
источник
доходность
пока
доходность
Разница в том, что
asd%20asd
противasd+asd
urlencode отличается от RFC 1738 кодированием пробелов, а
+
не%20
источник
Одна практическая причина выбрать один из других, если вы собираетесь использовать результат в другой среде, например, JavaScript.
В PHP
urlencode('test 1')
возвращается,'test+1'
аrawurlencode('test 1')
возвращается'test%201'
как результат.Но если вам нужно «декодировать» это в JavaScript с помощью функции decodeURI (), тогда
decodeURI("test+1")
вы получите"test+1"
время,decodeURI("test%201")
которое даст вам"test 1"
результат.Другими словами, пробел (""), закодированный urlencode в plus ("+") в PHP, не будет должным образом декодирован decodeURI. в JavaScript.
В таких случаях следует использовать PHP-функцию rawurlencode .
источник
json_encode
иJSON.parse
для этого.Я считаю, что пробелы должны быть закодированы как:
%20
при использовании внутри компонента пути URL+
при использовании внутри компонента строки запроса URL или данных формы (см. 17.13.4 Типы содержимого формы )В следующем примере показано правильное использование
rawurlencode
иurlencode
:Вывод:
Что произойдет, если вы закодируете компоненты пути и строки запроса наоборот? Для следующего примера:
latest+songs
вместоlatest songs
q
будет содержатьlady gaga
источник
q
будет содержатьlady gaga
» Что еще он будет содержать в противном случае?q
Кажется, что параметр запроса имеет одно и то же значение, передаваемое$_GET
массиву, независимо от использованияrawurlencode
илиurlencode
в PHP 5.2+. Тем не менее,urlencode
кодирует вapplication/x-www-form-urlencoded
формате, который по умолчанию для запросов GET, поэтому я иду с вашим подходом. +1+
и%20
декодируются как пространство при использовании в строках запроса.Разница заключается в возвращаемых значениях, то есть:
urlencode () :
rawurlencode () :
Эти два очень похожи, но последний (rawurlencode) заменит пробелы на «%» и две шестнадцатеричные цифры, что подходит для кодирования паролей и т. Д., Где «+» не является, например:
источник
1. Какие именно различия и
Разница лишь в способе обработки пространств:
urlencode - на основе унаследованной реализации преобразует пробелы в +
rawurlencode - на основе RFC 1738 переводит пробелы в% 20
Причина различия заключается в том, что + зарезервирован и действителен (не закодирован) в URL.
2. что является предпочтительным?
Справедливости ради, у меня есть простая стратегия, которой я придерживаюсь при принятии этих решений, которой я поделюсь с вами в надежде, что она может помочь.
Я думаю, что это была спецификация HTTP / 1.1 RFC 2616, которая требовала « толерантных приложений »
Когда возникают такие вопросы, лучшая стратегия всегда состоит в том, чтобы потреблять как можно больше и производить то, что соответствует стандартам.
Поэтому я советую использовать его
rawurlencode
для создания совместимых со стандартами строк в кодировке RFC 1738 и использоватьurldecode
для обеспечения обратной совместимости и приспособления к чему-либо, что вам может потребоваться.Теперь вы можете просто поверить мне на слово, но давайте докажем, что мы ...
Похоже, что PHP имел в виду именно это, хотя я никогда не сталкивался с тем, кто отказывается от любого из этих двух форматов, я не могу придумать более эффективную стратегию, чтобы принять ее как стратегию де-факто, не так ли?
NJoy!
источник
источник
Пробелы, закодированные как
%20
против+
Самая большая причина, которую я видел, чтобы использовать
rawurlencode()
в большинстве случаев, состоит в том, чтоurlencode
кодирует текстовые пространства как+
(знаки плюс), гдеrawurlencode
кодирует их как обычно видимый%20
:Я специально видел определенные конечные точки API, которые принимают закодированные текстовые запросы, ожидающие
%20
пробела и, как результат, потерпели неудачу, если вместо них использовался знак плюс. Очевидно, что это будет отличаться между реализациями API, и ваш пробег может отличаться.источник
Я считаю, что urlencode для параметров запроса, тогда как rawurlencode для сегментов пути. Это в основном связано с
%20
сегментами пути и+
параметрами запроса. Посмотрите этот ответ, который говорит о пробелах: когда кодировать пробел в плюс (+) или% 20?Однако
%20
теперь он работает и с параметрами запроса, поэтому rawurlencode всегда безопаснее. Однако знак «плюс» имеет тенденцию использоваться там, где имеет значение пользовательский опыт редактирования и удобочитаемость параметров запроса.Обратите внимание, что это означает,
rawurldecode
что не декодировать+
в пробелы ( http://au2.php.net/manual/en/function.rawurldecode.php ). Вот почему $ _GET всегда автоматически пропускаетсяurldecode
, что означает, что+
и%20
оба декодированные в пространствах.Если вы хотите, чтобы кодирование и декодирование были согласованы между входами и выходами, и вы выбрали всегда использовать,
+
а не%20
для параметров запроса, тоurlencode
это хорошо для параметров запроса (ключ и значение).Вывод:
Сегменты пути - всегда используйте rawurlencode / rawurldecode
Параметры запроса - для декодирования всегда используйте urldecode (выполняется автоматически), для кодирования подойдет и rawurlencode, или urlencode, просто выберите один из них для согласованности, особенно при сравнении URL-адресов.
источник
простой * rawurlencode путь - путь это часть перед "?" - пробелы должны быть закодированы как% 20 * urlencode строки запроса - Строка запроса является частью после "?" -пространства лучше кодируются как "+" = rawurlencode в целом более совместим
источник