Welche Zeichen machen eine URL ungültig?
Sind diese URLs gültig?
Beispiel.com/Datei[/].html
http://example.com/file[/].html
Im Allgemeinen können URIs, wie sie in RFC 3986 definiert sind (siehe Abschnitt 2: Zeichen), jedes der folgenden 84 Zeichen enthalten:
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~:/?#[]@!$&'()*+,;=
Beachten Sie, dass diese Liste nicht angibt, wo im URI diese Zeichen vorkommen dürfen.
Jedes andere Zeichen muss mit der Prozent-Kodierung (%
hh
) kodiert werden. Jeder Teil des URI hat weitere Einschränkungen, welche Zeichen durch ein prozentual kodiertes Wort dargestellt werden müssen.
Zur weiteren Klarstellung und um die obige Frage direkt anzusprechen, gibt es mehrere Klassen von Zeichen, die Probleme für URLs und URIs verursachen.
Es gibt einige Zeichen, die nicht erlaubt sind und niemals in einer URL/URI erscheinen sollten, reservierte Zeichen (unten beschrieben) und andere Zeichen, die in einigen Fällen Probleme verursachen können, aber als "unklug" gekennzeichnet sind; oder "unsicher" gekennzeichnet sind. Erläuterungen, warum die Zeichen eingeschränkt sind, sind in [RFC-1738][1] (URLs) und [RFC-2396][2] (URIs) klar dargelegt. Beachten Sie, dass der neuere [RFC-3986][3] (Aktualisierung zu RFC-1738) die Konstruktion dessen definiert, welche Zeichen in einem bestimmten Kontext erlaubt sind, während die ältere Spezifikation eine einfachere und allgemeinere Beschreibung der nicht erlaubten Zeichen mit den folgenden Regeln bietet.
Ausgeschlossene US-ASCII-Zeichen, die innerhalb der URI-Syntax nicht erlaubt sind:
control = <US-ASCII coded characters 00-1F and 7F hexadecimal>
space = <US-ASCII coded character 20 hexadecimal>
delims = "<" | ">" | "#" | "%" | <">
Das Zeichen "#" wird ausgeschlossen, weil es zur Abgrenzung einer URI von einem Fragmentbezeichner verwendet wird. Das Prozentzeichen "%" wird ausgeschlossen; wird ausgeschlossen, weil es für die Kodierung von maskierten Zeichen verwendet wird. Mit anderen Worten, das "#" und "%" sind reservierte Zeichen, die in einem bestimmten Kontext verwendet werden müssen.
Listen unkluger Zeichen sind zulässig, können aber Probleme verursachen:
unwise = "{" | "}" | "|" | "\" | "^" | "[" | "]" | "`"
Zeichen, die innerhalb einer Abfragekomponente reserviert sind und/oder innerhalb eines URI/URL eine besondere Bedeutung haben:
reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | ","
Das "reserviert"
Syntaxklasse oben bezieht sich auf die Zeichen, die innerhalb eines URIs erlaubt sind, die aber innerhalb einer bestimmten Komponente der generischen URI-Syntax möglicherweise nicht erlaubt sind.
Zeichen in der Syntaxklasse "reserved"
Satz sind nicht in allen Kontexten reserviert.
Der Hostname kann zum Beispiel einen optionalen Benutzernamen enthalten, so dass er so etwas wie ftp://user@hostname/
sein könnte, wobei die '@'
Zeichen eine besondere Bedeutung hat.
Hier ist ein Beispiel für eine URL, die ungültige und unkluge Zeichen enthält (z.B. '$', '[', ']') und ordnungsgemäß kodiert sein sollte:
http://mw1.google.com/mw-earth-vectordb/kml-samples/gp/seattle/gigapxl/$[level]/r$[y]_c$[x].jpg
Einige der Zeichenbeschränkungen für URIs/URLs sind programmiersprachenabhängig.
Zum Beispiel die '|'
(0x7C)-Zeichen, obwohl es nur als "unklug" gekennzeichnet ist;
in der URI-Spezifikation eine URISyntaxException im Java java.net.URI-Konstruktor auslöst, so dass eine URL wie http://api.google.com/q?exp=a|b
nicht erlaubt ist und stattdessen als http://api.google.com/q?exp=a%7Cb
kodiert werden muss, wenn Java mit einer URI-Objektinstanz verwendet wird.
[1]: http://www.ietf.org/rfc/rfc1738.txt [2]: http://www.ietf.org/rfc/rfc2396.txt [3]: http://www.ietf.org/rfc/rfc3986.txt
Die meisten der hier vorhandenen Antworten sind unpraktisch, weil sie den realen Gebrauch von Adressen wie
Nach dieser neueren Bedeutung von "URL", welche Zeichen sind erlaubt? In vielen Teilen der URL, wie dem Abfrage-String und dem Pfad, dürfen wir're beliebige "URL-Einheiten" verwenden, die
URL-Codepunkte und prozentcodierte Bytes. Was sind "URL-Codepunkte"?
Die URL-Codepunkte sind ASCII alphanumerisch, U+0021 (!), U+0024 ($), U+0026 (&), U+0027 ('), U+0028 LINKE PARENTHESE, U+0029 RECHTE PARENTHESE, 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 (~), und Codepunkte im Bereich U+00A0 bis U+10FFFD, einschließlich, ohne Surrogate und Nichtzeichen. (Beachten Sie, dass die Liste von "URL-Code Punkte" nicht't enthält
%
, aber dass%
s in "URL-Code-Einheiten" erlaubt sind; erlaubt sind, wenn sie'Teil einer Prozent-Codierungssequenz sind). Die einzige Stelle, an der ich erkennen kann, wo die Spezifikation die Verwendung jedes Zeichens erlaubt, das's nicht* in dieser Menge ist, ist im host, wo IPv6-Adressen in[
und]
Zeichen eingeschlossen sind. An allen anderen Stellen in der URL sind entweder URL-Einheiten oder ein noch restriktiverer Zeichensatz erlaubt.Welche Zeichen waren unter den alten RFCs erlaubt?
Um der Geschichte willen und da es's an anderer Stelle in den Antworten hier nicht vollständig erforscht wird, wurde let's Untersuchung unter dem älteren Paar von Spezifikationen erlaubt. Zunächst einmal haben wir zwei Arten von RFC 3986 [reservierte Zeichen] (https://tools.ietf.org/html/rfc3986#section-2.2):
:/?#[]@
, die Teil der generischen Syntax für eine in RFC 3986 definierte URI sind**, die't Teil der allgemeinen Syntax von RFC's sind, aber für die Verwendung als syntaktische Komponenten bestimmter URI-Schemata reserviert sind. So werden z.B. Semikolons und Kommas als Teil der Syntax von [Daten-URIs](https://en.wikipedia.org/wiki/Data_URI_scheme) verwendet, und
&und
=werden als Teil des allgegenwärtigen Formats
?foo=bar&qux=bazin Abfragezeichenketten (die in RFC 3986 spezifiziert *isn't* sind) verwendet. Jedes der oben genannten reservierten Zeichen kann legal in einem URI ohne Kodierung verwendet werden, entweder um ihren syntaktischen Zweck zu erfüllen oder einfach als literale Zeichen in Daten an einigen Stellen, wo eine solche Verwendung nicht als das Zeichen, das seinem syntaktischen Zweck dient, fehlinterpretiert werden könnte. (Obwohl z.B.
/in einem URL eine syntaktische Bedeutung hat, können Sie es unkodiert in einer Abfragezeichenfolge verwenden, weil es *nicht't* in einer Abfragezeichenfolge eine Bedeutung hat). RFC 3986 spezifiziert auch einige *unreservierte* Zeichen, die immer einfach verwendet werden können, um Daten ohne jegliche Kodierung darzustellen: **
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~`*
Schließlich ist das "%"-Zeichen selbst für Prozent-Codierungen erlaubt.
Damit bleiben nur die folgenden ASCII-Zeichen übrig, die in einer URL verboten* sind:
"<>\^`{|}
Jedes andere Zeichen aus ASCII kann legal in einer URL vorkommen.
Dann erweitert RFC 3987 diesen Satz von unreservierten Zeichen um die folgenden Unicode-Zeichenbereiche: %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
Schließlich ist es vielleicht noch erwähnenswert, dass das bloße Wissen, welche Zeichen legal in einer URL erscheinen dürfen, nicht ausreicht, um zu erkennen, ob eine bestimmte Zeichenfolge eine legale URL ist oder nicht, da einige Zeichen nur in bestimmten Teilen der URL legal sind.
Zum Beispiel sind die reservierten Zeichen [
und ]
als Teil eines IPv6-Wortlauts in einer URL wie http://[1080::8:800:200C:417A]/foo legal, aber nicht't legal in jedem anderen Kontext, so dass das OP's Beispiel von http://example.com/file[/].html
illegal ist.
1:
In Ihrer Zusatzfrage haben Sie gefragt, ob www.example.com/file[/].html
eine gültige URL ist.
Diese URL ist't gültig, weil eine URL ein Typ von URI ist und eine gültige URI ein Schema wie http:
haben muss (siehe [RFC 3986][1]).
Wenn Sie fragen wollten, ob http://www.example.com/file[/].html
eine gültige URL ist, dann ist die Antwort immer noch nein, weil die eckigen Klammerzeichen dort't gültig sind.
Die Zeichen in eckigen Klammern sind für URLs in diesem Format reserviert:
http://[2001:db8:85a3::8a2e:370:7334]/foo/bar
(i.e.
ein IPv6-Literal anstelle eines Hostnamens)
Es lohnt sich, RFC 3986 sorgfältig zu lesen, wenn Sie das Thema vollständig verstehen wollen.
Alle gültigen Zeichen, die in einem URI verwendet werden können (eine URL ist ein Typ von URI), sind in RFC 3986 definiert.
Alle anderen Zeichen können in einer URL verwendet werden, vorausgesetzt, sie werden zuerst "URL Encoded". Dabei wird das ungültige Zeichen gegen bestimmte "Codes" ausgetauscht (in der Regel in Form des Prozentzeichens (%), gefolgt von einer Hexadezimalzahl).
Dieser Link, HTML URL Encoding Reference, enthält eine Liste der Kodierungen für ungültige Zeichen.
Mehrere Unicode-Zeichenbereiche sind gültiges HTML5, obwohl es vielleicht immer noch keine gute Idee ist, sie zu verwenden.
In `href'-Dokumenten steht z.B. http://www.w3.org/TR/html5/links.html#attr-hyperlink-href:
Das href-Attribut auf a- und Bereichselementen muss einen Wert haben, der eine gültige URL ist, die möglicherweise von Leerzeichen umgeben ist.
Dann die Definition von "gültige URL" zeigt auf http://url.spec.whatwg.org/, was besagt, dass es darauf abzielt:
RFC 3986 und RFC 3987 an zeitgenössischen Implementierungen auszurichten und sie dabei zu veralten.
Dieses Dokument definiert URL code points als:
ASCII alphanumerisch, "!", ", "$", "&", ", "'", "(", ", ")", "*", "+", ", ", ", ", "-", ", ".", ", "/", ", "?", "@", ", "_", "~" und Codepunkte in den Bereichen U+00A0 bis U+D7FF, U+E000 bis U+FDCF, U+FDF0 bis U+FFFD, U+10000 bis U+1FFFD, U+20000 bis U+2FFFD, U+30000 bis U+3FFFD, U+40000 bis U+4FFFD, U+50000 bis U+5FFFD, U+60000 bis U+6FFFD, U+70000 bis U+7FFFD, U+80000 bis U+8FFFD, U+90000 bis U+9FFFD, U+A0000 bis U+AFFFFD, U+B0000 bis U+BFFFD, U+C0000 bis U+CFFFD, U+D0000 bis U+DFFFD, U+E1000 bis U+EFFFFD, U+F0000 bis U+FFFFD, U+100000 bis U+10FFFD.
Der Begriff "URL-Code Punkte" wird dann in der Anweisung verwendet:
Wenn c kein URL-Codepunkt ist und nicht "%", dann wird ein Parserfehler verwendet.
in mehreren Teilen des Parsing-Algorithmus, einschließlich des Schema-, Autoritäts-, relativen Pfad-, Abfrage- und Fragmentstatus: also im Grunde die gesamte URL.
Außerdem geht der Validator http://validator.w3.org/ für URLs wie "你好"
durch und nicht für URLs mit Zeichen wie Leerzeichen "a b"
.
Natürlich geht es, wie von Stephen C erwähnt, nicht nur um Zeichen, sondern auch um den Kontext: Sie müssen den gesamten Algorithmus verstehen. Aber da die Klasse "URL-Code Punkte" an Schlüsselpunkten des Algorithmus verwendet wird, gibt sie eine gute Vorstellung davon, was Sie verwenden können und was nicht.
Siehe auch: Siehe auch: https://stackoverflow.com/questions/2742852/unicode-characters-in-urls
Ich muss ein Zeichen auswählen, um die URLs in eine Zeichenfolge aufzuteilen, daher beschloss ich, eine Liste von Zeichen zu erstellen, die von mir selbst nicht in der URL gefunden werden konnten:
>>> allowed = "-_.~!*'();:@&=+$,/?%#[]?@ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
>>> from string import printable
>>> ''.join(set(printable).difference(set(allowed)))
'`" <\x0b\n\r\x0c\\\t{^}|>'
Die möglichen Auswahlmöglichkeiten sind also der Zeilenumbruch, Tabulator, Leerzeichen, Backslash und "<>{}^|
.
Ich schätze, I'wird mit dem Leerzeichen oder dem Zeilenumbruch gehen.
:)
Nicht wirklich eine Antwort auf Ihre Frage, aber die Validierung von URL' s ist wirklich eine ernsthafte p.i.t.a Sie sind wahrscheinlich besser dran, wenn Sie nur den Domänennamen validieren und den Abfrageteil der Url lassen. Das ist meine Erfahrung. Sie könnten auch die Url anpingen und sehen, ob sie eine gültige Antwort liefert, aber das könnte zu viel für eine so einfache Aufgabe sein.
Reguläre Ausdrücke zur Erkennung von Url's gibt es reichlich, googeln Sie es :)
Ich habe mir ein paar reguläre Ausdrücke für PHP ausgedacht, mit denen Urls im Text in Anker-Tags umgewandelt werden können. (Zuerst konvertiert es alle www. urls nach http://, dann konvertiert es alle urls mit https?:// in ein 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) );