Quali caratteri rendono un URL non valido?
Questi URL sono validi?
example.com/file[/].html
http://example.com/file[/].html
Quali caratteri rendono un URL non valido?
Questi URL sono validi?
example.com/file[/].html
http://example.com/file[/].html
Risposte:
In generale, gli URI definiti da RFC 3986 (vedere la Sezione 2: Caratteri ) possono contenere uno dei seguenti 84 caratteri:
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~:/?#[]@!$&'()*+,;=
Si noti che questo elenco non indica dove possono essere presenti questi caratteri nell'URI.
Ogni altro carattere deve essere codificato con la percentuale di codifica ( %
hh
). Ogni parte dell'URI ha ulteriori restrizioni su ciò che i personaggi devono essere rappresentati da una parola con codifica percentuale.
/^([!#$&-;=?-[]_a-z~]|%[0-9a-fA-F]{2})+$/
c'era qualcos'altro che hai scoperto che avrebbe dovuto accettare? (Per essere chiari, quel regex controlla solo se la stringa contiene caratteri URL validi, non se la stringa contiene un URL ben formato.)
Per aggiungere alcuni chiarimenti e rispondere direttamente alla domanda sopra, ci sono diverse classi di caratteri che causano problemi per URL e URI.
Ci sono alcuni caratteri che non sono consentiti e non dovrebbero mai apparire in un URL / URI, caratteri riservati (descritti di seguito) e altri caratteri che possono causare problemi in alcuni casi, ma sono contrassegnati come "poco saggio" o "non sicuro". Le spiegazioni del motivo per cui i caratteri sono limitati sono chiaramente enunciate in RFC-1738 (URL) e RFC-2396 (URI). Nota la più recente RFC-3986 (aggiornamento a RFC-1738) definisce la costruzione di quali caratteri sono ammessi in un determinato contesto, ma le specifiche più vecchie offrono una descrizione più semplice e più generale di quali caratteri non sono ammessi con le seguenti regole.
Caratteri US-ASCII esclusi non consentiti nella sintassi URI:
control = <US-ASCII coded characters 00-1F and 7F hexadecimal>
space = <US-ASCII coded character 20 hexadecimal>
delims = "<" | ">" | "#" | "%" | <">
Il carattere "#" è escluso perché viene utilizzato per delimitare un URI da un identificatore di frammento. Il carattere percentuale "%" è escluso perché viene utilizzato per la codifica dei caratteri di escape. In altre parole, "#" e "%" sono caratteri riservati che devono essere utilizzati in un contesto specifico.
L'elenco dei caratteri non saggi è consentito ma può causare problemi:
unwise = "{" | "}" | "|" | "\" | "^" | "[" | "]" | "`"
Caratteri che sono riservati all'interno di un componente di query e / o hanno un significato speciale all'interno di un URI / URL:
reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | ","
La classe di sintassi "riservata" riportata sopra si riferisce a quei caratteri consentiti all'interno di un URI, ma che potrebbero non essere consentiti all'interno di un particolare componente della sintassi URI generica. I caratteri nel set "riservato" non sono riservati in tutti i contesti . Il nome host, ad esempio, può contenere un nome utente opzionale, quindi potrebbe essere qualcosa di simile al punto in ftp://user@hostname/
cui il carattere "@" ha un significato speciale.
Ecco un esempio di un URL che ha caratteri non validi e poco saggi (ad esempio '$', '[', ']') e deve essere codificato correttamente:
http://mw1.google.com/mw-earth-vectordb/kml-samples/gp/seattle/gigapxl/$[level]/r$[y]_c$[x].jpg
Alcune delle restrizioni sui caratteri per URI / URL dipendono dal linguaggio di programmazione. Ad esempio, il '|' Il carattere (0x7C) sebbene contrassegnato solo come "non saggio" nelle specifiche URI genererà una URISyntaxException nel costruttore Java java.net.URI, pertanto un URL simile http://api.google.com/q?exp=a|b
non è consentito e deve essere codificato come http://api.google.com/q?exp=a%7Cb
se si utilizzasse Java con un'istanza di oggetto URI.
?
va bene nella sezione delle query, ma impossibile prima di essa, e non credo che @
appartenga a nessuno di questi elenchi. Oh, e invece %25
dell'ultima stringa, non intendi %7C
?
La maggior parte delle risposte esistenti qui sono poco pratiche perché ignorano totalmente l'uso nel mondo reale di indirizzi come:
Innanzitutto, una digressione nella terminologia. Quali sono questi indirizzi? Sono URL validi?
Storicamente, la risposta è stata "no". Secondo RFC 3986 , dal 2005, tali indirizzi non sono URI (e quindi non URL, poiché gli URL sono un tipo di URI ). Secondo la terminologia degli standard IETF del 2005, dovremmo chiamarli correttamente IRI (Internationalized Resource Identifier), come definito in RFC 3987 , che tecnicamente non sono URI ma possono essere convertiti in URI semplicemente codificando in percentuale tutti i caratteri non ASCII nell'IRI .
Per le specifiche moderne, la risposta è "sì". Il WHATWG Living standard classifica semplicemente tutto ciò che in precedenza si chiamava "URI" o "Iris" come "URL". Ciò allinea la terminologia specificata al modo in cui le persone normali che non hanno letto la specifica usano la parola "URL", che era uno degli obiettivi della specifica .
Per questo significato più recente di "URL", quali caratteri sono ammessi? In molte parti dell'URL, come la stringa di query e il percorso, è consentito utilizzare "unità URL" arbitrarie , che sono
Cosa sono i "punti di codice URL"?
I punti del codice URL sono alfanumerici ASCII, U + 0021 (!), U + 0024 ($), U + 0026 (&), U + 0027 ('), U + 0028 PARENTESI SINISTRA, U + 0029 PARENTESI DESTRA, 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 (~) e punti di codice nell'intervallo da U + 00A0 a U + 10FFFD, inclusi, esclusi surrogati e non personaggi.
(Si noti che l'elenco di "punti di codice URL" non include %
, ma che %
sono ammessi in "Unità di codice URL" se fanno parte di una sequenza di codifica percentuale.)
L'unico posto in cui posso individuare dove le specifiche consentono l'uso di qualsiasi carattere che non è in questo set è nell'host , dove sono racchiusi indirizzi IPv6 [
e ]
caratteri. Ovunque altro nell'URL, sono consentite unità URL o alcuni set di caratteri ancora più restrittivi.
Per il bene della storia, e dal momento che non è esplorato completamente altrove nelle risposte qui, esaminiamo era consentito sotto la vecchia coppia di specifiche.
Innanzitutto, abbiamo due tipi di caratteri riservati RFC 3986 :
:/?#[]@
, che fanno parte della sintassi generica per un URI definito in RFC 3986!$&'()*+,;=
, che non fanno parte della sintassi generica della RFC, ma sono riservati all'uso come componenti sintattici di particolari schemi URI. Ad esempio, virgola e virgole sono usati come parte della sintassi di URI dati , ed &
e =
sono utilizzati come parte della onnipresente ?foo=bar&qux=baz
formato stringhe di query (che non è specificato da RFC 3986).Qualsiasi dei caratteri riservati sopra può essere legalmente utilizzato in un URI senza codifica, sia per servire il loro scopo sintattico o semplicemente come caratteri letterali nei dati in alcuni luoghi in cui tale uso non potrebbe essere interpretato erroneamente come il personaggio che serve al suo scopo sintattico. (Ad esempio, sebbene /
abbia un significato sintattico in un URL, è possibile utilizzarlo non codificato in una stringa di query, poiché non ha significato in una stringa di query.)
RFC 3986 specifica anche alcuni caratteri senza prenotazione , che possono sempre essere utilizzati semplicemente per rappresentare i dati senza alcuna codifica:
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~
Infine, il %
carattere stesso è consentito per le codifiche in percentuale.
Ciò lascia solo i seguenti caratteri ASCII a cui è proibito apparire in un URL:
"<>\^`{|}
Ogni altro personaggio di ASCII può essere legalmente presente in un URL.
Quindi RFC 3987 estende quella serie di caratteri senza prenotazione con i seguenti intervalli di caratteri 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
Queste scelte di blocco dalle vecchie specifiche sembrano bizzarre e arbitrarie date le ultime definizioni di blocco Unicode ; ciò è probabilmente dovuto al fatto che i blocchi sono stati aggiunti nel decennio da quando è stato scritto RFC 3987.
Infine, forse vale la pena notare che la semplice conoscenza di quali caratteri possono apparire legalmente in un URL non è sufficiente per riconoscere se una determinata stringa è un URL legale o meno, poiché alcuni caratteri sono legali solo in particolari parti dell'URL. Ad esempio, i caratteri riservati [
e ]
sono legali come parte di un host letterale IPv6 in un URL come http: // [1080 :: 8: 800: 200C: 417A] / pippo ma non sono legali in nessun altro contesto, quindi il L'esempio di OP http://example.com/file[/].html
è illegale.
Nella tua domanda aggiuntiva hai chiesto se www.example.com/file[/].html
è un URL valido.
Tale URL non è valido perché un URL è un tipo di URI e un URI valido deve avere uno schema simile http:
(vedere RFC 3986 ).
Se intendevi chiedere se http://www.example.com/file[/].html
è un URL valido, la risposta è ancora no perché i caratteri tra parentesi quadre non sono validi lì.
I caratteri parentesi quadre sono riservati per gli URL in questo formato: http://[2001:db8:85a3::8a2e:370:7334]/foo/bar
(ovvero un valore letterale IPv6 anziché un nome host)
Vale la pena leggere attentamente RFC 3986 se si desidera comprendere appieno il problema.
[
e ]
non sono validi per quasi i parser che ho visto. Questo in realtà mi ha fregato nel mondo reale: stackoverflow.com/questions/11038967/…
Unwise
molto sul serio per gli URI e tuttavia andranno bene con le librerie URL. Cioè non c'è bandiera da ignorare Unwise
. Dovrò controllare cosa Rust lang (dal momento che è stato creato per un browser, sono curioso di sapere cosa fa) per gli URL. La maggior parte dei browser passerà felicemente anche "[", "]". Quindi in teoria, proprio come ho detto con C / C ++, sono sub / super, ma la realtà non è così vera. Dipende fortemente dall'interpretazione delle specifiche e della semantica del super / sottoinsieme.
Tutti i caratteri validi che possono essere utilizzati in un URI (un URL è un tipo di URI ) sono definiti in RFC 3986 .
Tutti gli altri caratteri possono essere utilizzati in un URL a condizione che siano prima "URL codificati". Ciò comporta la modifica del carattere non valido per "codici" specifici (di solito sotto forma del simbolo percentuale (%) seguito da un numero esadecimale).
Questo collegamento, HTML Encoding Reference , contiene un elenco delle codifiche per caratteri non validi.
Molte gamme di caratteri Unicode sono HTML5 valide , anche se potrebbe non essere una buona idea usarle.
Ad esempio, i href
documenti dicono http://www.w3.org/TR/html5/links.html#attr-hyperlink-href :
L'attributo href sugli elementi a e area deve avere un valore che sia un URL valido potenzialmente circondato da spazi.
Quindi la definizione di "URL valido" punta a http://url.spec.whatwg.org/ , che afferma che mira a:
Allinea RFC 3986 e RFC 3987 con implementazioni contemporanee e obsolete nel processo.
Tale documento definisce i punti del codice URL come:
ASCII alfanumerico, "!", "$", "&", "'", "(", ")", "*", "+", ",", "-", ".", "/" , ":", ";", "=", "?", "@", "_", "~" e punti di codice negli intervalli da U + 00A0 a U + D7FF, U + E000 a U + FDCF , U + FDF0 a U + FFFD, U + 10000 a U + 1FFFD, U + 20000 a U + 2FFFD, U + 30000 a U + 3FFFD, U + 40000 a U + 4FFFD, U + 50000 a U + 5FFFD, U Da +60000 a U + 6FFFD, U da + 70000 a U + 7FFFD, U da + 80000 a U + 8FFFD, U + 90000 a U + 9FFFD, U + A0000 a U + AFFFD, U + B0000 a U + BFFFD, U + C0000 a U + CFFFD, U + D0000 a U + DFFFD, U + E1000 a U + EFFFD, U + F0000 a U + FFFFD, U + 100000 a U + 10FFFD.
Il termine "punti di codice URL" viene quindi utilizzato nell'istruzione:
Se c non è un punto di codice URL e non "%", analizzare l'errore.
in diverse parti dell'algoritmo di analisi, inclusi lo schema, l'autorità, il percorso relativo, la query e gli stati dei frammenti: quindi sostanzialmente l'intero URL.
Inoltre, il validatore http://validator.w3.org/ passa per URL simili "你好"
e non per URL con caratteri come spazi"a b"
Ovviamente, come menzionato da Stephen C, non si tratta solo di personaggi ma anche di contesto: devi capire l'intero algoritmo. Ma poiché la classe "Punti del codice URL" viene utilizzata sui punti chiave dell'algoritmo, ciò fornisce una buona idea di ciò che è possibile utilizzare o meno.
Vedi anche: caratteri Unicode negli URL
Devo selezionare il carattere per dividere gli URL nella stringa, quindi ho deciso di creare un elenco di caratteri che non sono stati trovati nell'URL da solo:
>>> allowed = "-_.~!*'();:@&=+$,/?%#[]?@ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
>>> from string import printable
>>> ''.join(set(printable).difference(set(allowed)))
'`" <\x0b\n\r\x0c\\\t{^}|>'
Quindi, le possibili scelte sono newline, tab, space, backslash e "<>{}^|
. Immagino che andrò con lo spazio o la newline. :)
Non è davvero una risposta alla tua domanda, ma convalidare l'URL è davvero una pita seria Probabilmente stai solo meglio convalidando il nome di dominio e lasciare che la query sia parte dell'URL. Questa è la mia esperienza. Potresti anche ricorrere al ping dell'URL e vedere se si traduce in una risposta valida, ma potrebbe essere troppo per un'attività così semplice.
Le espressioni regolari per rilevare gli URL sono abbondanti, cercalo su Google :)
Sto implementando il vecchio lettore / scrittore di richieste e risposte http (0.9, 1.0, 1.1). L'URI di richiesta è il luogo più problematico.
Non puoi semplicemente usare RFC 1738, 2396 o 3986 così com'è. Esistono molti vecchi client e server HTTP che consentono più caratteri. Così ho fatto di ricerca sulla base accidentalmente pubblicati log di accesso server web: "GET URI HTTP/1.0" 200
.
Ho scoperto che i seguenti caratteri non standard sono spesso utilizzati nell'URI:
\ { } < > | ` ^ "
Questi caratteri sono stati descritti in RFC 1738 come non sicuri .
Se vuoi essere compatibile con tutti i vecchi client e server HTTP, devi consentire questi caratteri nell'URI di richiesta.
Si prega di leggere ulteriori informazioni su questa ricerca in http-og .
Ho trovato un paio di espressioni regolari per PHP che convertiranno gli URL nel testo in tag di ancoraggio. (Prima converte tutti gli URL www. In http: // quindi converte tutti gli URL con https?: // in un link 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)
);