Какие символы делают URL недопустимым?
Являются ли эти допустимые URL-адреса?
-
example.com/file[/].html
-
http://example.com/file[/].html
Какие символы делают URL недопустимым?
Являются ли эти допустимые URL-адреса?
example.com/file[/].html
http://example.com/file[/].html
Обычно URI, определенные в RFC 3986 (см. Раздел 2: символы), могут содержать любой из следующих 84 символов:
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~:/?#[]@!$&'()*+,;=
Обратите внимание, что в этом списке не указано, где в URI могут присутствовать эти символы.
Любой другой символ должен быть закодирован с помощью процентного кодирования (%
hh
). Каждая часть URI имеет дополнительные ограничения относительно того, какие символы должны быть представлены словом в кодировке процента.
Чтобы внести некоторые пояснения и напрямую обратиться к вышеуказанному вопросу, есть несколько классов символов, которые вызывают проблемы для 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.
Это не просто вопрос о персонажах. Различные символы являются законными в разных точках. Например, согласно 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"
"/file[/].html"
И путь должен анализироваться как '/' <segment> '/' <segment>
, где первый сегмент "file["
, а второй - "].html"
Большинство существующих ответов здесь нецелесообразно, поскольку они полностью игнорируют реальное использование таких адресов, как:
Во-первых, отступление к терминологии. Каковы эти адреса? Это действительные URL-адреса?
Исторически ответ был "нет". Согласно RFC 3986, с 2005 года такие адреса не являются URI (и, следовательно, не являются URL-адресами, поскольку URL-адреса являются типом URI). Согласно терминологии стандартов IETF 2005 года, мы должны правильно называть их IRI (интернационализированные идентификаторы ресурсов), как определено в RFC 3987, которые технически не являются URI, но могут быть преобразованы в URI просто путем процентного кодирования всех не -ASCII символы в IRI.
Согласно современной спецификации, ответ - "да". WHATWG Living Standard просто классифицирует все, что раньше называлось "URIs" или "IRI", как "URL". Это приводит терминологию в соответствие с тем, как обычные люди, которые не читали спецификацию, используют слово "URL", которое было одной из целей спецификации.
В соответствии с более новым значением "URL", какие символы разрешены? Во многих частях URL, таких как строка запроса и путь, нам разрешено использовать произвольные "единицы URL", которые являются
Что такое "кодовые точки 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 3986 зарезервированных символов:
:/?#[]@
, которые являются частью общего синтаксиса для URI, определенного в RFC 3986!$&'()*+,;=
, которые не являются частью общего синтаксиса RFC, но зарезервированы для использования в качестве синтаксических компонентов определенных схем URI. Например, точки с запятой и запятые используются как часть синтаксиса URI данных, а &
и =
используются как часть вездесущего формата ?foo=bar&qux=baz
в строках запроса (который не является указано в RFC 3986).Любой из вышеупомянутых зарезервированных символов может быть юридически использован в URI без кодирования, либо для обслуживания их синтаксической цели, либо просто в качестве буквенных символов в данных в некоторых местах, где такое использование не может быть неверно истолковано как символ, служащий его синтаксической цели. (Например, хотя /
имеет синтаксическое значение в URL-адресе, вы можете использовать его без кода в строке запроса, поскольку оно не имеет значения в строке запроса.)
RFC 3986 также определяет некоторые незарезервированные символы, которые всегда можно использовать просто для представления данных без какой-либо кодировки:
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~
Наконец, сам символ %
разрешен для процентного кодирования.
Это оставляет только следующие символы ASCII, которые запрещено появляться в URL:
"<>\^'{|}
Любой другой символ из 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
недопустим.
В дополнительном вопросе вы задали вопрос, является ли 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 HTML Encoding Reference, содержит список кодировок для недопустимых символов.
Несколько из диапазонов символов 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-адресах
Мне нужно выбрать символ для разделения URL-адресов в строке, поэтому я решил создать список символов, который сам по себе не найден в URL:
>>> allowed = "-_.~!*'();:@&=+$,/?%#[][email protected]"
>>> from string import printable
>>> ''.join(set(printable).difference(set(allowed)))
'`" <\x0b\n\r\x0c\\\t{^}|>'
Таким образом, возможны варианты: новая строка, табуляция, пробел, обратная косая черта и "<>{}^|
. Думаю, я пойду с пространством или новой линией.:)
Не совсем ответ на ваш вопрос, но проверка url действительно серьезная p.i.t.a Возможно, вам просто лучше проверить доменное имя и оставить запрос частью URL-адреса. Это мой опыт. Вы также можете прибегнуть к проверке URL-адреса и выяснению, приводит ли он к действительному ответу, но это может быть слишком большим для такой простой задачи.
Регулярные выражения для обнаружения URL-адреса в изобилии, google it:)
Используйте urlencode, чтобы разрешить произвольные символы в вашем URL-адресе.
Я придумал пару регулярных выражений для 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)
);