Które znaki powodują, że adres URL jest nieprawidłowy?
Czy to są prawidłowe adresy URL?
example.com/file[/].html
http://example.com/file[/].html
Które znaki powodują, że adres URL jest nieprawidłowy?
Czy to są prawidłowe adresy URL?
example.com/file[/].html
http://example.com/file[/].html
Odpowiedzi:
Zasadniczo identyfikatory URI zdefiniowane w RFC 3986 (patrz sekcja 2: Znaki ) mogą zawierać dowolny z następujących 84 znaków:
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~:/?#[]@!$&'()*+,;=
Zauważ, że ta lista nie określa, gdzie w URI mogą wystąpić te znaki.
Każdy inny znak musi być zakodowany za pomocą metody procentowej ( %
hh
). Każda część identyfikatora URI ma dalsze ograniczenia dotyczące tego, jakie znaki muszą być reprezentowane przez słowo zakodowane w procentach.
/^([!#$&-;=?-[]_a-z~]|%[0-9a-fA-F]{2})+$/
Czy było coś, co odkryłeś, że powinno to akceptować? (Żeby było jasne, to wyrażenie regularne sprawdza tylko, czy ciąg zawiera prawidłowe znaki adresu URL, a nie czy ciąg zawiera dobrze sformułowany adres URL.)
Aby dodać wyjaśnienia i bezpośrednio odpowiedzieć na powyższe pytanie, istnieje kilka klas znaków, które powodują problemy z adresami URL i identyfikatorami URI.
Niektóre znaki są niedozwolone i nigdy nie powinny pojawiać się w adresie URL / URI, znakach zastrzeżonych (opisanych poniżej) i innych znakach, które mogą powodować problemy w niektórych przypadkach, ale są oznaczone jako „nierozsądne” lub „niebezpieczne”. Wyjaśnienia, dlaczego znaki są ograniczone, są jasno określone w RFC-1738 (adresy URL) i RFC-2396 (URI). Uwaga: nowsza wersja RFC-3986 (aktualizacja RFC-1738) definiuje konstrukcję dozwolonych znaków w danym kontekście, ale starsza specyfikacja oferuje prostszy i bardziej ogólny opis, które znaki są niedozwolone przy zastosowaniu następujących reguł.
Wykluczone znaki US-ASCII niedozwolone w składni URI:
control = <US-ASCII coded characters 00-1F and 7F hexadecimal>
space = <US-ASCII coded character 20 hexadecimal>
delims = "<" | ">" | "#" | "%" | <">
Znak „#” jest wykluczony, ponieważ służy do oddzielenia identyfikatora URI od identyfikatora fragmentu. Znak procentu „%” jest wykluczony, ponieważ jest używany do kodowania znaków specjalnych. Innymi słowy, „#” i „%” są znakami zastrzeżonymi, których należy użyć w określonym kontekście.
Lista niemądrych znaków jest dozwolona, ale może powodować problemy:
unwise = "{" | "}" | "|" | "\" | "^" | "[" | "]" | "`"
Znaki zastrzeżone w komponencie zapytania i / lub mające specjalne znaczenie w URI / URL:
reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | ","
„Zarezerwowana” klasa składni powyżej odnosi się do tych znaków, które są dozwolone w ramach identyfikatora URI, ale które mogą nie być dozwolone w ramach określonego komponentu ogólnej składni URI. Znaki w zestawie „zastrzeżone” nie są zarezerwowane we wszystkich kontekstach . Na przykład nazwa hosta może zawierać opcjonalną nazwę użytkownika, więc może to być coś w rodzaju, ftp://user@hostname/
gdzie znak „@” ma specjalne znaczenie.
Oto przykład adresu URL, który zawiera niepoprawne i nierozsądne znaki (np. „$”, „[”, „]”) I powinien być odpowiednio zakodowany:
http://mw1.google.com/mw-earth-vectordb/kml-samples/gp/seattle/gigapxl/$[level]/r$[y]_c$[x].jpg
Niektóre ograniczenia znaków dla identyfikatorów URI / adresów URL zależą od języka programowania. Na przykład „|” (0x7C), chociaż tylko oznaczony jako „nierozsądny” w specyfikacji URI, wyrzuci wyjątek URISyntaxException do konstruktora Java java.net.URI, więc adres URL podobny http://api.google.com/q?exp=a|b
jest niedozwolony i zamiast tego należy go zakodować, tak jak http://api.google.com/q?exp=a%7Cb
przy użyciu Java z instancją obiektu URI.
?
jest w porządku w sekcji zapytania, ale przedtem jest niemożliwa i nie sądzę, że @
należy do żadnej z tych list. Aha, a nie %25
w ostatnim ciągu, nie masz na myśli %7C
?
Większość istniejących tutaj odpowiedzi jest niepraktyczna, ponieważ całkowicie ignorują rzeczywiste użycie adresów, takich jak:
Najpierw dygresja w terminologii. Jakie są te adresy? Czy są to prawidłowe adresy URL?
Historycznie odpowiedź brzmiała „nie”. Zgodnie z RFC 3986 od 2005 r. Takie adresy nie są identyfikatorami URI (a zatem nie są adresami URL, ponieważ adresy URL są rodzajem identyfikatorów URI ). Zgodnie z terminologią standardów IETF z 2005 r. Powinniśmy właściwie nazywać je IRI (Internacjonalizowane identyfikatory zasobów), jak zdefiniowano w RFC 3987 , które technicznie nie są identyfikatorami URI, ale mogą być konwertowane na identyfikatory URI poprzez proste kodowanie procentowe wszystkich znaków spoza ASCII w IRI .
Według współczesnej specyfikacji odpowiedź brzmi „tak”. WHATWG standardu życia po prostu klasyfikuje wszystko, czego wcześniej się nazywać „URI” lub „IRIS” AS „URL”. To wyrównuje specced terminologia z jak normalni ludzie, którzy nie czytali spec używać słowa „URL”, który był jednym z Spec za celami .
Jakie znaki są dozwolone w nowym znaczeniu „URL”? W wielu częściach URL, takich jak ciąg kwerendy i ścieżki, mamy możliwość korzystania arbitralnych „jednostek URL” , które są
Co to są „punkty kodu URL”?
Te punkty kodowe adresu URL to ASCII alfanumeryczny U + 0021 (!), U + 0024 ($), U + 0026 (&), U + 0027 ( '), U + 0028 nawias U + 0029 nawiasie 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 (~) i punkty kodowe w zakresie od U + 00A0 do U + 10FFFD włącznie, z wyłączeniem surogatów i znaków innych niż znaki.
(Uwaga: lista „punktów kodu URL” nie obejmuje %
, ale %
są one dozwolone w „Jednostkach kodu URL”, jeśli są one częścią sekwencji kodującej procentowo).
Jedynym miejscem, w którym mogę dostrzec, gdzie specyfikacja pozwala na użycie dowolnego znaku spoza tego zestawu, jest host , w którym zawarte są adresy IPv6 [
i ]
znaki. Gdzie indziej w adresie URL dozwolone są jednostki URL lub niektóre bardziej restrykcyjne zestawy znaków.
Ze względu na historię, a ponieważ nie została ona w pełni zbadana gdzie indziej w odpowiedziach tutaj, zbadajmy dozwoloną pod starszą parą specyfikacji.
Przede wszystkim mamy dwa typy znaków zastrzeżonych RFC 3986 :
:/?#[]@
, które są częścią ogólnej składni identyfikatora URI zdefiniowanego w RFC 3986!$&'()*+,;=
, które nie są częścią ogólnej składni RFC, ale są zarezerwowane do użycia jako składniki składniowe poszczególnych schematów URI. Na przykład, średniki i przecinki są stosowane jako część składni URI danych i &
i =
są stosowane jako część wszechobecnego ?foo=bar&qux=baz
formacie w ciągi zapytania (który nie jest określony w specyfikacji RFC 3986).Dowolny z zastrzeżonych znaków powyżej może być legalnie używany w URI bez kodowania, albo w celu spełnienia ich celu składniowego, albo po prostu jako dosłowne znaki w danych w niektórych miejscach, w których takie użycie nie mogło być źle interpretowane jako znak spełniający swój cel syntaktyczny. (Na przykład, chociaż /
ma składniowe znaczenie w adresie URL, możesz użyć go niezakodowanego w ciągu zapytania, ponieważ nie ma ono znaczenia w ciągu zapytania).
RFC 3986 określa również niektóre niezarezerwowane znaki, których zawsze można użyć do przedstawienia danych bez żadnego kodowania:
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~
Wreszcie %
sam znak jest dopuszczony do kodowania procentowego.
Że pozostawia tylko następujących znaków ASCII, które są zakazane pojawianiu się w adresie URL:
"<>\^`{|}
Każda inna postać z ASCII może legalnie występować w adresie URL.
Następnie RFC 3987 rozszerza ten zestaw niezastrzeżonych znaków o następujące zakresy znaków 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
Te wybory bloków ze starej specyfikacji wydają się dziwne i arbitralne, biorąc pod uwagę najnowsze definicje bloków Unicode ; dzieje się tak prawdopodobnie dlatego, że bloki zostały dodane do dekady od czasu napisania RFC 3987.
Wreszcie, być może warto zauważyć, że sama wiedza, które znaki mogą legalnie pojawić się w adresie URL, nie wystarcza, aby rozpoznać, czy dany ciąg jest legalnym adresem URL, czy nie, ponieważ niektóre znaki są dozwolone tylko w określonych częściach adresu URL. Na przykład znaki zastrzeżone [
i ]
są legalne jako część hosta dosłownego IPv6 w adresie URL takim jak http: // [1080 :: 8: 800: 200C: 417A] / foo, ale nie są legalne w żadnym innym kontekście, więc Przykład OP http://example.com/file[/].html
jest nielegalny.
W dodatkowym pytaniu zapytałeś, czy www.example.com/file[/].html
jest prawidłowym adresem URL.
Ten adres URL jest nieprawidłowy, ponieważ adres URL jest typem identyfikatora URI, a prawidłowy identyfikator URI musi mieć podobny schemat http:
(patrz RFC 3986 ).
Jeśli chciałeś zapytać, czy http://www.example.com/file[/].html
jest to prawidłowy adres URL, odpowiedź brzmi „nie”, ponieważ znaki nawiasu kwadratowego są tam niepoprawne.
Znaki nawiasu kwadratowego są zarezerwowane dla adresów URL w tym formacie: http://[2001:db8:85a3::8a2e:370:7334]/foo/bar
(tzn. Literał IPv6 zamiast nazwy hosta)
Warto dokładnie przeczytać RFC 3986, jeśli chcesz w pełni zrozumieć problem.
[
I ]
nie są ważne przez URI prawie parserami widziałem. To mnie naprawdę wkręciło w prawdziwym świecie: stackoverflow.com/questions/11038967/...
Unwise
bardzo poważnie dla URI, a mimo to będą w porządku z bibliotekami URL. Oznacza to, że nie ma flagi do zignorowania Unwise
. Będę musiał sprawdzić, co Rust lang (ponieważ jest budowany dla przeglądarki, jestem ciekawy, co robi) dla adresów URL. Jednak większość przeglądarek również z radością przekazuje „[”, „]”. Teoretycznie, tak jak powiedziałem w C / C ++, są sub / super, ale rzeczywistość nie jest tak prawdziwa. Jest wysoce zależny od interpretacji specyfikacji i semantyki super / podzbioru.
Wszystkie prawidłowe znaki, które mogą być użyte w URI ( URL to typ URI ) są zdefiniowane w RFC 3986 .
Wszystkie pozostałe znaki mogą być użyte w adresie URL, pod warunkiem, że są one najpierw „zakodowane w adresie URL”. Obejmuje to zmianę nieprawidłowego znaku dla określonych „kodów” (zwykle w postaci symbolu procentu (%), po którym następuje liczba szesnastkowa).
Ten link, HTML Encoding Reference , zawiera listę kodowań nieprawidłowych znaków.
Kilka zakresów znaków Unicode jest prawidłowych HTML5 , chociaż ich użycie może nadal nie być dobrym pomysłem.
Np. href
Doktorzy mówią : http://www.w3.org/TR/html5/links.html#attr-hyperlink-href :
Atrybut href w elementach a i area musi mieć wartość, która jest prawidłowym adresem URL potencjalnie otoczonym spacjami.
Następnie definicja „prawidłowego adresu URL” wskazuje na http://url.spec.whatwg.org/ , co oznacza, że jego celem jest:
Dostosuj RFC 3986 i RFC 3987 do współczesnych implementacji i przestarzałe w tym procesie.
Ten dokument definiuje punkty kodu URL jako:
ASCII alfanumeryczne, „!”, „$”, „&”, „” „,” („,”) ”,„ * ”,„ + ”,„, ”,„ - ”,„. ”,„ / ” , ":", ";", "=", "?", "@", "_", "~" i punkty kodowe w zakresie od U + 00A0 do U + D7FF, U + E000 do U + FDCF , U + FDF0 do U + FFFD, U + 10000 do U + 1FFFD, U + 20000 do U + 2FFFD, U + 30000 do U + 3FFFD, U + 40000 do U + 4FFFD, U + 50000 do U + 5FFFD, U +60000 do U + 6FFFD, U + 70000 do U + 7FFFD, U + 80000 do U + 8FFFD, U + 90000 do U + 9FFFD, U + A0000 do U + AFFFD, U + B0000 do U + BFFFD, U + C0000 do U + CFFFD, U + D0000 do U + DFFFD, U + E1000 do U + EFFFD, U + F0000 do U + FFFFD, U + 100000 do U + 10FFFD.
Termin „punkty kodowe URL” jest następnie używany w instrukcji:
Jeśli c nie jest punktem kodowym adresu URL, a nie „%”, przeanalizuj błąd.
w kilku częściach algorytmu analizującego, w tym schemacie, autorytecie, ścieżce względnej, zapytaniu i stanach fragmentów: w zasadzie cały adres URL.
Ponadto walidator http://validator.w3.org/ podaje adresy URL podobne "你好"
i nie przekazuje adresów URL zawierających znaki takie jak spacje"a b"
Oczywiście, jak wspomniał Stephen C, nie chodzi tylko o znaki, ale także o kontekst: musisz zrozumieć cały algorytm. Ale ponieważ klasa „Punkty kodu URL” jest używana w kluczowych punktach algorytmu, daje to dobre wyobrażenie o tym, czego możesz użyć, czy nie.
Zobacz także: Znaki Unicode w adresach URL
Muszę wybrać znak, aby podzielić adresy URL na ciąg, więc postanowiłem utworzyć listę znaków, których nie mogłem znaleźć w adresie URL:
>>> allowed = "-_.~!*'();:@&=+$,/?%#[]?@ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
>>> from string import printable
>>> ''.join(set(printable).difference(set(allowed)))
'`" <\x0b\n\r\x0c\\\t{^}|>'
Możliwe opcje to nowa linia, tabulacja, spacja, ukośnik odwrotny i "<>{}^|
. Chyba pójdę ze spacją lub nową linią. :)
Naprawdę nie jest to odpowiedź na twoje pytanie, ale sprawdzenie poprawności adresu URL to naprawdę poważna pita. Prawdopodobnie lepiej sprawdzić poprawność nazwy domeny i pozostaw część zapytania w adresie URL. To jest moje doświadczenie. Możesz również użyć polecenia ping do adresu URL i sprawdzić, czy spowoduje to prawidłową odpowiedź, ale może to być zbyt wiele jak na tak proste zadanie.
Wyrażenia regularne do wykrywania adresów URL są obfite, google :)
Wdrażam stary czytnik / pisarz zapytań i odpowiedzi http (0.9, 1.0, 1.1). Żądanie URI to najbardziej problematyczne miejsce.
Nie można tak po prostu używać RFC 1738, 2396 lub 3986. Istnieje wiele starych klientów HTTP i serwerów, które pozwalają na więcej znaków. Więc zrobiłem badania na podstawie przypadkowo opublikowane dzienniki dostępu webserver: "GET URI HTTP/1.0" 200
.
Odkryłem, że w URI często używane są następujące niestandardowe znaki:
\ { } < > | ` ^ "
Znaki te zostały opisane w RFC 1738 jako niebezpieczne .
Jeśli chcesz być zgodny ze wszystkimi starymi klientami i serwerami HTTP - musisz zezwolić tym znakom na żądanie URI.
Proszę przeczytać więcej informacji o tych badaniach w http-og .
Wymyśliłem kilka wyrażeń regularnych dla PHP, które konwertują adresy URL w tekście na tagi zakotwiczenia. (Najpierw konwertuje wszystkie adresy URL na http: //, a następnie konwertuje wszystkie adresy URL za pomocą https?: // na href = ... linki HTML
$string = preg_replace('/(https?:\/\/)([!#$&-;=?\-\[\]_a-z~%]+)/sim', '<a href="$1$2">$2</a>',
preg_replace('/(\s)((www\.)([!#$&-;=?\-\[\]_a-z~%]+))/sim', '$1http://$2', $string)
);