Какие символы делают URL недействительным? - PullRequest
465 голосов
/ 10 октября 2009

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

Это действительные URL?

Ответы [ 9 ]

552 голосов
/ 10 октября 2009

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

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

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

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

170 голосов
/ 21 ноября 2012

Чтобы добавить некоторые пояснения и напрямую обратиться к вышеуказанному вопросу, есть несколько классов символов, которые вызывают проблемы для 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://user@hostname/, где символ '@' имеет особое значение.

Вот пример 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.

70 голосов
/ 16 апреля 2016

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

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

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

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

.

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

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

кодовые точки URL и байты, закодированные в процентах .

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

Кодовые точки URL представляют собой буквенно-цифровые символы ASCII, U + 0021 (!), U + 0024 ($), U + 0026 (&), U + 0027 ('), U + 0028 ЛЕВОЙ РОДИТЕЛЬ , U + 0029 ПРАВЫЙ РОДИТЕЛЬ, 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 (~) и код точки в диапазоне от U + 00A0 до U + 10FFFD включительно, исключая суррогаты и нехарактеры.

(Обратите внимание, что список «кодовых точек 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 незаконно.

19 голосов
/ 03 декабря 2009

В дополнительном вопросе вы спросили, является ли 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, если вы хотите полностью понять проблему.

11 голосов
/ 10 октября 2009

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

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

Эта ссылка, Справочник по кодированию URL-адресов HTML , содержит список кодировок для недопустимых символов.

9 голосов

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

Например, href документы говорят 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 как:

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-адресах

5 голосов
/ 11 февраля 2014

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

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

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

4 голосов
/ 10 октября 2009

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

Регулярные выражения для определения URL-адресов в изобилии, Google это:)

0 голосов
/ 26 декабря 2016

Я придумал пару регулярных выражений для PHP, которые преобразуют URL-адреса в тексте в теги привязки. (Сначала он преобразует все URL-адреса www. В 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) );

...