Które znaki powodują, że adres URL jest nieprawidłowy?
Czy to są prawidłowe adresy URL?
example.com/file[/].htmlhttp://example.com/file[/].html
Które znaki powodują, że adres URL jest nieprawidłowy?
Czy to są prawidłowe adresy URL?
example.com/file[/].htmlhttp://example.com/file[/].htmlOdpowiedzi:
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|bjest niedozwolony i zamiast tego należy go zakodować, tak jak http://api.google.com/q?exp=a%7Cbprzy 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 %25w 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=bazformacie 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[/].htmljest nielegalny.
W dodatkowym pytaniu zapytałeś, czy www.example.com/file[/].htmljest 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[/].htmljest 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/...
Unwisebardzo 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. hrefDoktorzy 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)
);