Какие символы делают URL недействительным?
Являются ли эти URL действительными?
example.com/file[/].html
http://example.com/file[/].html
В общем случае URI, определенные в RFC 3986 (см. Раздел 2: Символы), могут содержать любой из следующих 84 символов:
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~:/?#[]@!$&'()*+,;=
Обратите внимание, что в этом списке не указано, где в URI могут встречаться эти символы.
Любой другой символ должен быть закодирован с помощью кодировки percent-encoding (%
hh
). Каждая часть URI имеет дополнительные ограничения на то, какие символы должны быть представлены словом с кодировкой percent.
Чтобы добавить некоторые пояснения и непосредственно обратиться к вопросу выше, есть несколько классов символов, которые вызывают проблемы для 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, будет помещать URISyntaxException в конструктор Java java.net.URI , поэтому URL-адрес, такой как http://api.google.com / q?exp = a | b
не допускается и должен быть закодирован как http://api.google.com/q?exp = a% 7Cb
при использовании Java с экземпляром объекта URI.
Большинство существующих ответов здесь нецелесообразны, потому что они полностью игнорируют реальное использование адресов, таких как:
Во-первых, отступление в терминологию. Что это за адреса?? Являются ли они действительными URL?
Исторически ответ был «нет». Согласно RFC 3986, с 2005 года такие адреса не являются URI (и, следовательно, не URL-адресами, поскольку URL-адреса [являются типом URI](https://tools.ietf.org/html/rfc3986. Согласно терминологии стандартов IETF 2005 года, мы должны правильно называть их IRI (интернационализированные идентификаторы ресурсов), как определено в RFC 3987, которые технически не являются URI, но могут быть преобразованы в URI просто путем кодирования процентов всех не-ASCII символов в IRI
По современной спецификации ответ «да». WHATWG Living Standard просто классифицирует все, что ранее называлось «URI» или «IRI», как «URL». Это выравнивает терминологию с надписью с тем, как нормальные люди, которые не читали спецификацию, используют слово «URL», которое было одной из [целей] спецификации 1.
По этому более новому значению «URL», какие символы разрешены? Во многих частях URL, таких как строка запроса и путь, нам разрешено использовать произвольные «единицы URL», которые являются
[Кодовые точки URL](https://url.spec.whatwg.org/#url-кодовые точки) и [процентно-кодированные байты](https://url.spec.whatwg.org/#percent-encoded- Байт).
Что такое «точки кода URL»?
Точки кода URL являются буквенно-цифровыми ASCII, U + 0021 (!), U + 0024 ($), U + 0026 (&), U + 0027 ('), U + 0028 ЛЕВЫЙ РОДИТЕЛЬ, U + 0029 ПРАВЫЙ РОДИТЕЛЬСТВО, U + 002A (*), U + 002B (+), U + 00).), U + 002F (/), U + 003A (:), U + 003B (;), U + 003D (=), U + 003F (?), U + 0040 (@), U + 005F (_), U + 007E (~) и кодовые точки в диапазоне от U + 00A0 до U + 10FFFD включительно, за исключением суррогатов и несимволов.
(Обратите внимание, что список «точек кода URL» не включает %
, но что %
s разрешены в «единицах кода URL», если они являются частью последовательности кодирования процентов.)
Единственное место, где я могу определить, где спецификация позволяет использовать любой символ, который не в этом наборе, находится в host, где IPv6 адреса заключены в символы [
и ]
. В любом другом месте URL разрешены либо единицы URL, либо еще более ограничительный набор символов.
Ради истории, и поскольку она не полностью исследована в других разделах ответов, давайте рассмотрим, что было разрешено в соответствии со старой парой спецификаций.
Прежде всего, у нас есть два типа RFC 3986 зарезервированные символы:
: /?# [] @
, которые являются частью общего синтаксиса для URI, определенного в RFC 3986**, которые не являются частью общего синтаксиса RFC, но зарезервированы для использования в качестве синтаксических компонентов определенных схем URI. Например, точки с запятой и запятые используются как часть синтаксиса [URI данных](https://en.wikipedia.org/wiki/Data_URI_scheme), а
&и
=используются как часть вездесущего
?foo = bar & qux = baz` формат в строках запроса (который не указан в RFC 3986).Любой из зарезервированных символов выше может быть юридически использован в URI без кодирования, либо для обслуживания их синтаксического назначения, либо просто в качестве буквальных символов в данных в некоторых местах, где такое использование не может быть неверно истолковано как символ, служащий его синтаксическому назначению. (Например, хотя /
имеет синтаксическое значение в URL, вы можете использовать его в кодировке в строке запроса, поскольку он не имеет значение в строке запроса.)
RFC 3986 также указывает некоторые незарезервированные символы, которые всегда можно использовать просто для представления данных без какой-либо кодировки:
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._ ~
Наконец, сам символ %
разрешен для процентных кодировок.
Это оставляет только следующие символы ASCII, которые запрещены , появляться в URL:
Любой другой символ из ASCII может легально отображаться в URL
Затем RFC 3987 расширяет этот набор не зарезервированных символов следующими диапазонами символов Unicode:
%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-адресе, не равно 39;t достаточно, чтобы распознать, является ли какая-то заданная строка законным URL или нет, поскольку некоторые символы являются законными только в определенных частях URL. Например, зарезервированные символы [
и ]
являются законными как часть буквального хоста IPv6 в URL-адресе, таком как http://[1080 :: 8: 800: 200C: 417A]/ foo, но есть и # 39;T законно в любом другом контексте, так что OP 's пример http://example.com/file[/].html
незаконно.
В своем дополнительном вопросе вы спросили, является ли 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, если вы хотите полностью понять проблему.
Все допустимые символы, которые могут быть использованы в URI (URL - это тип URI), определены в RFC 3986.
Все остальные символы могут быть использованы в URL при условии, что они сначала будут "закодированы". Это предполагает замену недопустимого символа на определенный "код" (обычно в виде символа процента (%), за которым следует шестнадцатеричное число).
Эта ссылка, HTML URL Encoding Reference, содержит список кодировок для недопустимых символов.
Несколько диапазонов символов Unicode являются допустимыми HTML5 , хотя их использование может быть не очень хорошей идеей.
Например., href
docs говорят http://www.w3.org/TR/html5/links.html#attr-hyperlink-href:
Атрибут href для элементов a и области должен иметь значение, которое является допустимым URL-адресом, потенциально окруженным пробелами.
Затем определение «действительный URL» указывает на http://url.spec.whatwg.org/, который говорит, что он стремится:
Совместите RFC 3986 и RFC 3987 с современными реализациями и устаревшими в процессе.
Этот документ определяет [ кодовые точки URL ](https://url.spec.whatwg.org/#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 + DFFD, U + E1000 до U + EFFFD, U + F0000 до U + FFFD, От U + 100000 до U + 10FFFD .
Термин «точки кода URL» затем используется в выражении:
Если c не является точкой кода URL, а не "%", ошибка анализа.
в нескольких частях алгоритма синтаксического анализа, включая состояния схемы, полномочий, относительного пути, запроса и фрагмента: так что в основном весь URL .
Кроме того, валидатор http://validator.w3.org/ проходит для URL-адресов, таких как " 你 好 "
, и не передает URL-адреса с символами, такими как пробелы "a b"
Конечно, как упомянул Стивен С, речь идет не только о символах, но и о контексте: вы должны понимать весь алгоритм. Но поскольку класс «точки кода URL» используется в ключевых точках алгоритма, это дает хорошее представление о том, что вы можете использовать или нет.
Смотрите также: https://stackoverflow.com/questions/2742852/unicode-characters-in-urls
Мне нужно выбрать символ, чтобы разделить URL-адреса на строки, поэтому я решил создать список символов, которые не могли быть найдены в URL самостоятельно:
>>> allowed = "-_.~!*'();:@&=+$,/?%#[]?@ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
>>> from string import printable
>>> ''.join(set(printable).difference(set(allowed)))
'`" <\x0b\n\r\x0c\\\t{^}|>'
Таким образом, возможными вариантами являются новая строка, вкладка, пробел, обратная косая черта и " < > {{{}}} ^ |
. Я думаю, я пойду с пространством или новой линией. :)
Это не совсем ответ на ваш вопрос, но валидация url действительно является серьезной проблемой. Вам, вероятно, лучше просто проверить доменное имя и оставить часть запроса в url. Это мой опыт. Вы также можете прибегнуть к пингу url и посмотреть, приведет ли он к правильному ответу, но это может быть слишком сложно для такой простой задачи.
Регулярных выражений для определения url существует великое множество, погуглите :)
Я придумал пару регулярных выражений для PHP, которые будут преобразовывать URL в тексте в якорные теги. (Сначала он преобразует все www. urls на http:// затем преобразует все urls в https?: // до href =... HTML ссылки
$ string = preg_replace ('/ (https?: \ / \ /) ([!# $ & -; =?\ - \ [\] _a-z ~%] +) / sim ',' < a href = "$ 1 $ 2" > $ 2 < / a > ', preg_replace ('/ (\ s) ((www \.) ([!# $ & -; =?\ - \ [\] _a-z ~%] +)) / sim ',' $ 1http:// $ 2 ', $ string) );