Какие символы недействительны?

Какие символы делают URL недопустимым?

Являются ли эти допустимые URL-адреса?

  • example.com/file[/].html
  • http://example.com/file[/].html

Ответ 1

Обычно URI, определенные в RFC 3986 (см. Раздел 2: символы), могут содержать любой из следующих 84 символов:

ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~:/?#[]@!$&'()*+,;=

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

Любой другой символ должен быть закодирован с помощью процентного кодирования (% hh). Каждая часть URI имеет дополнительные ограничения относительно того, какие символы должны быть представлены словом в кодировке процента.

Ответ 2

Чтобы внести некоторые пояснения и напрямую обратиться к вышеуказанному вопросу, есть несколько классов символов, которые вызывают проблемы для URL-адресов и URI.

Есть некоторые символы, которые запрещены и никогда не должны появляться в URL/URI, зарезервированных символах (описанных ниже) и других символах, которые могут вызывать проблемы в некоторых случаях, но помечаются как "неразумные" или "небезопасные". Объяснения причин ограничения символов четко изложены в RFC-1738 (URL-адреса) и RFC-2396 (URI). Обратите внимание, что более новый RFC-3986 (обновление до RFC-1738) определяет конструкцию символов, которые разрешены в данном контексте, но более старая спецификация предлагает более простое и более общее описание того, какие символы недопустимы с помощью следующие правила.

Исключенные символы US-ASCII, запрещенные в синтаксисе URI:

   control     = <US-ASCII coded characters 00-1F and 7F hexadecimal>
   space       = <US-ASCII coded character 20 hexadecimal>
   delims      = "<" | ">" | "#" | "%" | <">

Символ "#" исключен, поскольку он используется для ветки URI от идентификатора фрагмента. Символ процента "%" исключен, поскольку он используется для кодирования экранированных символов. Другими словами, "#" и "%" являются зарезервированными символами, которые должны использоваться в определенном контексте.

Список неразумных символов разрешен, но может вызвать проблемы:

   unwise      = "{" | "}" | "|" | "\" | "^" | "[" | "]" | "'"

Символы, которые зарезервированы в компоненте запроса и/или имеют специальное значение в URI/URL:

  reserved    = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | ","

Вышеуказанный "зарезервированный" синтаксический класс относится к тем символам, которые разрешены в URI, но которые не могут быть разрешены в конкретном компоненте общего синтаксиса URI. Символы в "зарезервированном" наборе не зарезервированы во всех контекстах. Например, имя хоста может содержать необязательное имя пользователя, поэтому это может быть что-то вроде ftp://[email protected]/, где символ "@" имеет особое значение.

Вот пример URL, который содержит недопустимые и неразумные символы (например, "$", "[','] ') и должен быть правильно закодирован:

http://mw1.google.com/mw-earth-vectordb/kml-samples/gp/seattle/gigapxl/$[level]/r$[y]_c$[x].jpg

Некоторые ограничения символов для URI/URL-адресов зависят от языка программирования. Например, '|' (0x7C), хотя в спецификации URI помечен только как "неразумный", в конструкторе Java java.net.URI будет выброшено исключение URISyntaxException, поэтому URL-адрес, такой как http://api.google.com/q?exp=a|b, недопустим и должен кодироваться вместо этого как http://api.google.com/q?exp=a%7Cb, если используется Java с экземпляром объекта URI.

Ответ 3

Это не просто вопрос о персонажах. Различные символы являются законными в разных точках. Например, согласно RFC 2396, unescaped '?' является законным в части фрагмента, но не частью пути.

Вам нужно прочитать RFC 2396, чтобы понять подробности... или задать более конкретный вопрос. Или, если вы действительно имеете в виду URI, а не URL, RFC 3986 - это то, что вы должны читать.


Вы спрашиваете, действительный ли URL example.com/file[/].html.

Я согласен с Домиником Сейерсом - Нет. URL должен иметь явную схему, такую ​​как "http", а затем ':'.

Но затем Доминик говорит, что http://example.com/file[/].html тоже не является допустимым URL, и это не так ясно.

Символы '[' и ']' являются символами <reserved> и должны иметь процент экранирования, если не использоваться в качестве разделителей в синтаксисе, специфичном для схемы. Спектр говорит:

"URI, создающие приложения, должны иметь октеты данных с процентным кодированием, которые соответствуют символам зарезервированного набора, если только эти символы не разрешены схемой URI для представления данных в этом компоненте."

(Примечание - оперативное слово здесь "должно", а не "должно" или "необходимо". Этот язык является рекомендательным, а не предписывающим.)

Следующее предложение спецификации говорит следующее:

"Если зарезервированный символ найден в компоненте URI, и для этого символа не определена роль разграничения, тогда его следует интерпретировать как представляющий октет данных, соответствующий этой кодировке символов в US-ASCII."

(Обратите внимание, что оперативное слово "must". Это говорит о том, что означает URI, если кто-то игнорирует совет предыдущего предложения.)

Итак, как это применимо здесь? Хорошо HTTP - это "иерархическая" схема, а общий ABNF для иерархических схем не говорит о том, что '[' или ']' являются разделителями в <path>. С другой стороны, ABNF говорит, что a <path segment> состоит из символов <unreserved>, <sub-delimiters>, процентов-кодированных символов, ':' или '@'. Другими словами, '[' или ']' не допускаются строгим чтением ABNF.

Таким образом, строго "http://example.com/file[/].html" недействительно. Но если вы столкнулись с таким URL (и не решили отклонить его), более ранняя часть спецификации говорит о том, что символы '[' и ']' должны рассматриваться как символы данных. Таким образом, URL-адрес будет анализироваться как:

  • схема == "http"
  • авторитет == "example.com"
  • path == "/file[/].html"

И путь должен анализироваться как '/' <segment> '/' <segment>, где первый сегмент "file[", а второй - "].html"

Ответ 4

Большинство существующих ответов здесь нецелесообразно, поскольку они полностью игнорируют реальное использование таких адресов, как:

Во-первых, отступление к терминологии. Каковы эти адреса? Это действительные URL-адреса?

Исторически ответ был "нет". Согласно RFC 3986, с 2005 года такие адреса не являются URI (и, следовательно, не являются URL-адресами, поскольку URL-адреса являются типом URI). Согласно терминологии стандартов IETF 2005 года, мы должны правильно называть их IRI (интернационализированные идентификаторы ресурсов), как определено в RFC 3987, которые технически не являются URI, но могут быть преобразованы в URI просто путем процентного кодирования всех не -ASCII символы в IRI.

Согласно современной спецификации, ответ - "да". WHATWG Living Standard просто классифицирует все, что раньше называлось "URIs" или "IRI", как "URL". Это приводит терминологию в соответствие с тем, как обычные люди, которые не читали спецификацию, используют слово "URL", которое было одной из целей спецификации.

Какие символы разрешены в соответствии со стандартом жизни WHATWG?

В соответствии с более новым значением "URL", какие символы разрешены? Во многих частях URL, таких как строка запроса и путь, нам разрешено использовать произвольные "единицы URL", которые являются

URL code points и percent-encoded bytes.

Что такое "кодовые точки URL"?

The URL code points are ASCII alphanumeric, U+0021 (!), U+0024 ($), U+0026 (&), U+0027 ('), U+0028 LEFT PARENTHESIS, U+0029 RIGHT PARENTHESIS, U+002A (*), U+002B (+), U+002C (,), U+002D (-), U+002E (.), U+002F (/), U+003A (:), U+003B (;), U+003D (=), U+003F (?), U+0040 (@), U+005F (_), U+007E (~), и code points in the range U+00A0 to U+10FFFD, inclusive, excluding surrogates и noncharacters.

(Обратите внимание, что список "кодовых точек URL" не включает в себя %, но % допускается в "кодовых единицах URL", если они являются частью последовательности кодирования процентов.)

Единственное место, которое я могу определить, где спецификация разрешает использование любого символа, которого нет в этом наборе, находится на хосте, где адреса IPv6 заключены в символы [ и ]. Повсюду в URL разрешены либо единицы измерения URL, либо еще более ограничительный набор символов.

Какие символы были разрешены по старым RFC?

Ради истории, и так как он не был полностью исследован в других местах в ответах здесь, пусть исследование разрешено в соответствии со старшей парой спецификаций.

Прежде всего, у нас есть два типа RFC 3986 зарезервированных символов:

  • :/?#[]@, которые являются частью общего синтаксиса для URI, определенного в RFC 3986
  • !$&'()*+,;=, которые не являются частью общего синтаксиса RFC, но зарезервированы для использования в качестве синтаксических компонентов определенных схем URI. Например, точки с запятой и запятые используются как часть синтаксиса URI данных, а & и = используются как часть вездесущего формата ?foo=bar&qux=baz в строках запроса (который не является указано в RFC 3986).

Любой из вышеупомянутых зарезервированных символов может быть юридически использован в URI без кодирования, либо для обслуживания их синтаксической цели, либо просто в качестве буквенных символов в данных в некоторых местах, где такое использование не может быть неверно истолковано как символ, служащий его синтаксической цели. (Например, хотя / имеет синтаксическое значение в URL-адресе, вы можете использовать его без кода в строке запроса, поскольку оно не имеет значения в строке запроса.)

RFC 3986 также определяет некоторые незарезервированные символы, которые всегда можно использовать просто для представления данных без какой-либо кодировки:

  • abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~

Наконец, сам символ % разрешен для процентного кодирования.

Это оставляет только следующие символы ASCII, которые запрещено появляться в URL:

  • Управляющие символы (символы 0-1F и 7F), включая новую строку, символ табуляции и возврат каретки.
  • "<>\^'{|}

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

Затем RFC 3987 расширяет этот набор незарезервированных символов следующими диапазонами символов Юникода:

  %xA0-D7FF / %xF900-FDCF / %xFDF0-FFEF
/ %x10000-1FFFD / %x20000-2FFFD / %x30000-3FFFD
/ %x40000-4FFFD / %x50000-5FFFD / %x60000-6FFFD
/ %x70000-7FFFD / %x80000-8FFFD / %x90000-9FFFD
/ %xA0000-AFFFD / %xB0000-BFFFD / %xC0000-CFFFD
/ %xD0000-DFFFD / %xE1000-EFFFD

Эти варианты блоков из старой спецификации кажутся странными и произвольными, учитывая последние определения блоков Unicode; Вероятно, это связано с тем, что блоки были добавлены за десятилетие, прошедшее с момента написания RFC 3987.


Наконец, возможно, стоит отметить, что простого знания того, какие символы могут юридически появляться в URL-адресе, недостаточно для определения того, является ли данная строка допустимым URL-адресом или нет, поскольку некоторые символы допустимы только в определенных частях URL-адреса. Например, зарезервированные символы [ и ] допустимы как часть литерального хоста IPv6 в URL-адресе, подобном http://[1080::8:800:200C:417A]/foo, но недопустимы в любом другом контексте, поэтому пример OP http://example.com/file[/].html недопустим.

Ответ 5

В дополнительном вопросе вы задали вопрос, является ли www.example.com/file[/].html допустимым URL.

Этот URL-адрес недействителен, потому что URL-адрес является типом URI, а допустимый URI должен иметь схему типа http: (см. RFC 3986).

Если вы хотите спросить, является ли http://www.example.com/file[/].html допустимым URL-адресом, тогда ответа по-прежнему нет, потому что символы квадратной скобки там недействительны.

Символы с квадратной скобкой зарезервированы для URL-адресов в этом формате: http://[2001:db8:85a3::8a2e:370:7334]/foo/bar (т.е. литерал IPv6 вместо имени хоста)

Стоит внимательно прочитать RFC 3986, если вы хотите полностью понять проблему.

Ответ 6

Все допустимые символы, которые можно использовать в URI (URL является типом URI), определены в RFC 3986.

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

Эта ссылка, HTML HTML Encoding Reference, содержит список кодировок для недопустимых символов.

Ответ 7

Несколько из диапазонов символов Unicode действительны HTML5, хотя, возможно, это не будет хорошей идеей их использования.

Например, href docs say http://www.w3.org/TR/html5/links.html#attr-hyperlink-href:

Атрибут href для элементов a и area должен иметь значение, которое является допустимым URL, потенциально окруженным пробелами.

Тогда определение "действительный URL" указывает на http://url.spec.whatwg.org/, в котором говорится, что он нацелен на:

Выполните выравнивание RFC 3986 и RFC 3987 с помощью современных реализаций и устаревших в процессе.

Этот документ определяет URL-коды URL как:

ASCII буквенно-цифровые, "!", "$", "&", "'", "(", ")", "*", "+", ",", "-", ".", "/", ":", ";", "=", "?", "@", "_", "~" и кодовые точки в диапазонах U + 00A0 до U + D7FF, U + E000 U + FDCF, U + FDF0 до U + FFFD, U + 10000 - U + 1FFFD, U + 20000 - U + 2FFFD, U + 30000 - U + 3FFFD, U + 40000 - U + 4FFFD, U + 50000 - U + 5FFFD, U + 60000 - U + 6FFFD, U + 70000 - U + 7FFFD, U + 80000 - U + 8FFFD, U + 90000 - U + 9FFFD, U + A0000 - U + AFFFD, U + B0000 - U + BFFFD, U + C0000 - U + CFFFD, U + D0000 - U + DFFFD, U + E1000 - U + EFFFD, U + F0000 - U + FFFFD, U + 100000 - U + 10FFFD.

В заявлении используется термин "URL-коды кодов":

Если c не является кодовой точкой URL, а не "%", ошибка синтаксического анализа.

в нескольких частях алгоритма синтаксического анализа, включая отношения схемы, полномочий, относительного пути, запроса и фрагмента: так что в основном весь URL.

Кроме того, валидатор http://validator.w3.org/ передает URL-адреса, такие как "你好", и не передает URL-адреса с такими символами, как пробелы "a b"

Конечно, как упоминал Стивен С, речь идет не только о персонажах, но и о контексте: вы должны понимать весь алгоритм. Но поскольку в ключевых точках алгоритма используется класс "URL-коды кода", это дает хорошее представление о том, что вы можете использовать или нет.

Смотрите также: символы Юникода в URL-адресах

Ответ 8

Мне нужно выбрать символ для разделения URL-адресов в строке, поэтому я решил создать список символов, который сам по себе не найден в URL:

>>> allowed = "-_.~!*'();:@&=+$,/?%#[][email protected]"
>>> from string import printable
>>> ''.join(set(printable).difference(set(allowed)))
'`" <\x0b\n\r\x0c\\\t{^}|>'

Таким образом, возможны варианты: новая строка, табуляция, пробел, обратная косая черта и "<>{}^|. Думаю, я пойду с пространством или новой линией.:)

Ответ 9

Не совсем ответ на ваш вопрос, но проверка url действительно серьезная p.i.t.a Возможно, вам просто лучше проверить доменное имя и оставить запрос частью URL-адреса. Это мой опыт. Вы также можете прибегнуть к проверке URL-адреса и выяснению, приводит ли он к действительному ответу, но это может быть слишком большим для такой простой задачи.

Регулярные выражения для обнаружения URL-адреса в изобилии, google it:)

Ответ 10

Используйте urlencode, чтобы разрешить произвольные символы в вашем URL-адресе.

Ответ 11

Я придумал пару регулярных выражений для PHP, которые преобразуют URL-адреса в текст для привязки тегов. (Сначала он преобразует все www. Urls в http://затем преобразует все URL-адреса с помощью https?://в href=... html links

$string = preg_replace('/(https?:\/\/)([!#$&-;=?\-\[\]_a-z~%]+)/sim', '<a href="$1$2">$2</a>', preg_replace('/(\s)((www\.)([!#$&-;=?\-\[\]_a-z~%]+))/sim', '$1http://$2', $string) );