Quali caratteri rendono un URL non valido?

Quali caratteri rendono un URL non valido?

Sono questi URL validi?

  • example.com/file[/].html
  • http://example.com/file[/].html

In generale URI come definito da RFC 3986 (vedi Sezione 2: Caratteri ) può contenere uno dei seguenti caratteri:

 ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~:/?#[]@!$&'()*+,;= 

Si noti che questo elenco non indica dove nell’URI possono verificarsi questi caratteri.

Qualsiasi altro personaggio deve essere codificato con la codifica % ( % hh ). Ogni parte dell’URI ha ulteriori restrizioni su quali caratteri devono essere rappresentati da una parola codificata in percentuale.

Per aggiungere qualche chiarimento e rispondere direttamente alla domanda di cui sopra, ci sono diverse classi di caratteri che causano problemi per URL e URI.

Alcuni caratteri non sono consentiti e non dovrebbero mai apparire in un URL / URI, in caratteri riservati (descritti di seguito) e in altri caratteri che potrebbero causare problemi in alcuni casi, ma sono contrassegnati come “imprudente” o “non sicuro”. Spiegazioni sul motivo per cui i caratteri sono limitati sono chiaramente enunciati in RFC-1738 (URL) e RFC-2396 (URI). Notare che il più recente RFC-3986 (aggiornamento a RFC-1738) definisce la costruzione di quali caratteri sono consentiti in un determinato contesto, ma la specifica precedente offre una descrizione più semplice e più generale di quali caratteri non sono consentiti con le seguenti regole.

Caratteri ASCII esclusi esclusi dalla syntax URI:

  control =  space =  delims = "< " | ">" | "#" | "%" | < "> 

Elenco di caratteri non validi sono ammessi ma possono causare problemi:

  unwise = "{" | "}" | "|" | "\" | "^" | "[" | "]" | "`" 

Caratteri riservati all’interno di un componente di query e / o con significato speciale all’interno di un URI / URL:

  reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | "," 

La class di syntax “riservata” sopra si riferisce a quei caratteri che sono consentiti all’interno di un URI, ma che potrebbero non essere consentiti all’interno di un particolare componente della syntax 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 come ftp://user@hostname/ dove il carattere ‘@’ ha un significato speciale.

Ecco un esempio di URL con caratteri non validi e non validi (ad esempio ‘$’, ‘[‘, ‘]’) e dovrebbe essere codificato correttamente:

 http://mw1.google.com/mw-earth-vectordb/kml-samples/gp/seattle/gigapxl/$[level]/r$[y]_c$[x].jpg 

Alcune restrizioni sui caratteri per URI / URL dipendono dal linguaggio di programmazione. Ad esempio, il ‘|’ (0x7C), anche se solo contrassegnato come “imprudente” nelle specifiche URI genererà una URISyntaxException nel costruttore Java java.net.URI, quindi un URL come 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 utilizza Java con un’istanza di object URI.

La maggior parte delle risposte esistenti qui sono poco pratiche perché ignorano totalmente l’uso reale di indirizzi come:

Va bene, quindi secondo RFC 3986 , tali indirizzi non sono URI (e quindi non URL, poiché gli URL sono un tipo di URI ). Se ci consideriamo vincolati alla terminologia degli standard IETF esistenti, dovremmo chiamarli correttamente IRI (Internationalized Resource Identifiers), come definito nella RFC 3987 , che tecnicamente non sono URI ma possono essere convertiti in URI semplicemente con la codifica percentuale di tutti i non -ASCII caratteri nell’IRI. Le persone normali, però, non hanno mai sentito parlare di IRI e semplicemente chiamano questi URI o URL (e in effetti c’è uno sforzo WHATWG in corso per creare una nuova specifica URL più ampia che semplicemente classifica tutti gli “URI” e “IRI” come “URL” per allineare con l’uso moderno di questi termini nel mondo reale).

Supponiamo di voler adottare immediatamente questo significato di URL (che mette in dubbio le specifiche IETF, ma ci allinea con l’uso quotidiano). In tal caso, quali caratteri sono validi in un URL?

Prima di tutto, abbiamo due tipi di caratteri riservati di RFC 3986:

  • :/?#[]@ , che fanno parte della syntax generica per un URI definito in RFC 3986
  • !$&'()*+,;= , che non fanno parte della syntax generica di RFC, ma sono riservati per l’uso come componenti sintattiche di particolari schemi URI. Ad esempio, virgola e virgola sono usati come parte della syntax degli URI dei dati , e & e = sono usati come parte del formato ubiquitous ?foo=bar&qux=baz nelle stringhe di query (che non è specificato da RFC 3986).

Uno qualsiasi dei caratteri riservati di cui 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 può essere interpretato erroneamente come il personaggio al servizio del suo scopo sintattico. (Ad esempio, sebbene / abbia un significato sintattico in un URL, puoi usarlo non codificato in una stringa di query, perché non ha significato in una stringa di query.)

RFC 3986 specifica anche alcuni caratteri non riservati , che possono sempre essere utilizzati semplicemente per rappresentare i dati senza alcuna codifica:

  • abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~

Infine, il carattere % stesso è consentito per le codifiche percentuali.

Questo lascia solo i seguenti caratteri ASCII a cui è vietato apparire in un URL:

  • I caratteri di controllo (caratteri 0-1F e 7F), tra cui nuova riga, tabulazione e ritorno a capo.
  • "<>\^`{|}

Ogni altro personaggio di ASCII può essere incluso legalmente in un URL.

Quindi RFC 3987 estende quel set di caratteri non riservati 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 

Ma quelle scelte di blocco sembrano bizzarre e arbitrarie viste le ultime definizioni dei blocchi Unicode; questo probabilmente perché i blocchi sono stati aggiunti nel decennio da quando è stato scritto RFC 3987. Le specifiche in corso di WhatWG hanno una lista più generosa :

Da U + 00A0 a U + D7FF, da U + E000 a U + FDCF, da U + FDF0 a U + FFFD, da U + 10000 a U + 1FFFD, da U + 20000 a U + 2FFFD, da U + 30000 a U + 3FFFD, U + Da 40000 a U + 4FFFD, da U + 50000 a U + 5FFFD, da U + 60000 a U + 6FFFD, da U + 70000 a U + 7FFFD, da U + 80000 a U + 8FFFD, da U + 90000 a U + 9FFFD, da U + A0000 a U + AFFFD, da U + B0000 a U + BFFFD, da U + C0000 a U + CFFFD, da U + D0000 a U + DFFFD, da U + E0000 a U + EFFFD, da U + F0000 a U + FFFFD, da U + 100000 a U + 10FFFD

Naturalmente, va notato che semplicemente sapere quali caratteri possono legalmente apparire in un URL non è sufficiente per riconoscere se una certa stringa è un URL legale o meno, dal momento che alcuni caratteri sono solo legali in parti particolari dell’URL. Ad esempio, i caratteri riservati [ e ] sono legali come parte di un host IPv6 letterale in un URL come http: // [1080 :: 8: 800: 200C: 417A] / foo ma non sono legali in nessun altro contesto, quindi l’esempio dell’OP di http://example.com/file[/].html è illegale.

Nella tua domanda supplementare 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 come http: (vedi RFC 3986 ).

Se intendevi chiedere se http://www.example.com/file[/].html è un URL valido, la risposta è ancora no perché i caratteri della parentesi quadra non sono validi lì.

I caratteri della parentesi quadra sono riservati agli URL in questo formato: http://[2001:db8:85a3::8a2e:370:7334]/foo/bar (cioè un valore letterale IPv6 invece di un nome host)

Vale la pena leggere attentamente l’RFC 3986 se si vuole comprendere pienamente il problema.

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 purché siano “URL codificati” per primi. Ciò comporta la modifica del carattere non valido per specifici “codici” (solitamente nella forma del simbolo di percentuale (%) seguito da un numero esadecimale).

Questo link, Riferimento di codifica URL HTML , contiene un elenco delle codifiche per i caratteri non validi.

Molti degli intervalli di caratteri Unicode sono HTML5 validi , sebbene potrebbe non essere ancora una buona idea utilizzarli.

Ad esempio, i documenti href dicono http://www.w3.org/TR/html5/links.html#attr-hyperlink-href :

L’attributo href sugli elementi area e deve avere un valore che è un URL valido potenzialmente circondato da spazi.

Quindi la definizione di “URL valido” punta a http://url.spec.whatwg.org/ , che dice che mira a:

Allineare RFC 3986 e RFC 3987 con implementazioni contemporanee e obsolete nel processo.

Questo documento definisce i punti del codice URL come:

ASCII alfanumerico, “!”, “$”, “&”, “‘”, “(“, “)”, “*”, “+”, “,”, “-“, “.”, “/” , “:”, “;”, “=”, “?”, “@”, “_”, “~” e punti di codice negli intervalli da U + 00A0 a U + D7FF, da 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, da U + 70000 a U + 7FFFD, da U + 80000 a U + 8FFFD, da U + 90000 a U + 9FFFD, da U + A0000 a U + AFFFD, da U + B0000 a U + BFFFD, da U + C0000 a U + CFFFD, da U + D0000 a U + DFFFD, da U + E1000 a U + EFFFD, da U + F0000 a U + FFFFD, da U + 100000 a U + 10FFFD.

Il termine “punti codice URL” viene quindi utilizzato nell’istruzione:

Se c non è un punto codice URL e non “%”, errore di analisi.

in diverse parti dell’algoritmo di analisi, inclusi lo schema, l’autorità, il percorso relativo, gli stati delle query e dei frammenti: in pratica l’intero URL.

Inoltre, il validatore http://validator.w3.org/ passa per URL come "你好" e non passa per URL con caratteri come spazi "ab"

Naturalmente, come citato da Stephen C, non si tratta solo di personaggi ma anche di contesto: devi capire l’intero algoritmo. Ma dal momento che la class “punti di codice URL” è usata sui punti chiave dell’algoritmo, ciò dà una buona idea di cosa puoi usare o meno.

Vedi anche: caratteri Unicode negli URL

Non è davvero una risposta alla tua domanda, ma la validazione dell’URL è davvero una pita seria Probabilmente stai solo meglio convalidando il nome del dominio e lascia che la parte della query dell’url sia. Questa è la mia esperienza. Potresti anche ricorrere al ping dell’URL e vedere se il risultato è una risposta valida, ma potrebbe essere troppo per un compito così semplice.

Le espressioni regolari per rilevare gli URL sono abbondanti, google 🙂

Ho bisogno di selezionare il carattere per dividere gli URL nella stringa, quindi ho deciso di creare un elenco di caratteri che non è stato ansible trovare nell’URL da solo:

 >>> allowed = "-_.~!*'();:@&=+$,/?%#[]?@ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" >>> from string import printable >>> ''.join(set(printable).difference(set(allowed))) '`" < \x0b\n\r\x0c\\\t{^}|>' 

Quindi, le scelte possibili sono newline, tab, space, backslash e "<>{}^| . Suppongo che andrò con lo spazio o newline 🙂

Ho trovato un paio di espressioni regolari per PHP che convertiranno gli URL nel testo in tag di ancoraggio. (In primo luogo converte tutti i www. Urls in http: // quindi converte tutti gli URL con https?: // in un href = … collegamenti html

$string = preg_replace('/(https?:\/\/)([!#$&-;=?\-\[\]_a-z~%]+)/sim', '$2', preg_replace('/(\s)((www\.)([!#$&-;=?\-\[\]_a-z~%]+))/sim', '$1http://$2', $string) );

Utilizza urlencode per consentire caratteri arbitrari nel tuo URL.