Подтвердить что ты не робот

Urlencode() символ 'звездочка' (звезда?)

Я тестирую PHP urlencode() против Java java.net.URLEncoder.encode().

Java

String all = "";
for (int i = 32; i < 256; ++i) {
    all += (char) i;
}

System.out.println("All characters:         -||" + all + "||-");
try {
    System.out.println("Encoded characters:     -||" + URLEncoder.encode(all, "utf8") + "||-");
} catch (UnsupportedEncodingException e) {
    e.printStackTrace();
}

PHP

$all = "";
for($i = 32; $i < 256; ++$i)
{
    $all = $all.chr($i);
}

echo($all.PHP_EOL);
echo(urlencode(utf8_encode($all)).PHP_EOL);

Все символы, похоже, кодируются одинаково с обеими функциями, за исключением символа "звездочка", который не закодирован Java, и переводится на% 2A с помощью PHP. Какое поведение должно быть "правильным", если оно есть?

Примечание. Я тоже пытался с rawurlencode() - не повезло.

4b9b3361

Ответ 1

В URL-адресе нормально иметь * (но это также нормально иметь в кодированной форме).

RFC1738: Единые указатели ресурсов (URL) содержит следующее:

Зарезервировано:

[...]

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

Таким образом, только буквенно-цифровые символы, специальные символы "$-_.+!*'()," и   зарезервированные символы, используемые для зарезервированных целей , могут использоваться   unencoded в URL-адресе.

С другой стороны, символы, которые не требуются для кодирования   (включая буквенно-цифровые символы) могут быть закодированы в рамках конкретной схемы   часть URL-адреса, если они не используются для зарезервированного   Цель.

Ответ 2

Wikipedia предлагает, что * является зарезервированным символом, когда дело доходит до URI, и что оно должно быть закодировано, если оно не используется для зарезервированных цель. Согласно RFC3986, страницы 12-13:

URI включают компоненты и подкомпоненты, которые ограничены  символов в "зарезервированном" наборе. Эти символы называются   "зарезервировано", потому что они могут (или не могут) быть определены как разделители  общий синтаксис, каждый синтаксис конкретной схемы или  специфичный для реализации синтаксис алгоритма разыменования URI.  Если данные для компонента URI будут конфликтовать с зарезервированным  в качестве разделителя, тогда конфликтующие данные должны быть  процентного кодирования до формирования URI.

  reserved    = gen-delims / sub-delims

  gen-delims  = ":" / "/" / "?" / "#" / "[" / "]" / "@"

  sub-delims  = "!" / "$" / "&" / "'" / "(" / ")"
              / "*" / "+" / "," / ";" / "="

(Тот факт, что URL RFC по-прежнему позволяет символу * идти незарегистрированным, то есть не имеет зарезервированной цели я URL-адреса и, следовательно, не должны быть закодированы. Так что вам нужно его закодировать или нет, зависит от того, какой тип URI вы создаете.)

Ответ 3

Javadoc URLEncoder относится к спецификации HTML:

Этот класс содержит статические методы для преобразования String в формат application/x-www-form-urlencoded MIME. Для получения дополнительной информации о кодировании HTML-формы обратитесь к спецификации HTML.

HTML4 довольно неясен в отношении этого вопроса и относится к RFC1738, который цитируется aioobe:

Управляющие имена и значения экранируются. Символы пробела заменяются на "+", а затем зарезервированные символы экранируются, как описано в [RFC1738], раздел 2.2: Номера буквенно-цифровых символов заменяются на "% HH", знак процента и две шестнадцатеричные цифры, представляющие код ASCII персонаж. Разрывы строк представлены как пары "CR LF" (то есть "% 0D% 0A" ).

Однако HTML5 прямо заявляет, что * не должен быть закодирован:

  • Если символ не находится в диапазоне U + 0020, U + 002A, U + 002D, U + 002E, U + 0030 - U + 0039, U + 0041 - U + 005A, U + 005F, U + 0061 - U + 007A
    Замените символ строкой, сформированной следующим образом:
    ...
  • В противном случае
    Оставьте символ как есть.