Was ist gültig und was ist nicht in einer URI-Abfrage enthalten?

99

Hintergrund (Frage weiter unten)

Ich habe dies hin und her gegoogelt und RFCs und SO-Fragen gelesen, um dies zu knacken, aber ich habe immer noch keinen Jack.

Ich denke, wir stimmen einfach für die "beste" Antwort und das wars, oder?

Im Grunde läuft es darauf hinaus.

3.4. Abfragekomponente

Die Abfragekomponente ist eine Informationsfolge, die von der Ressource interpretiert werden soll.

query = *uric

Innerhalb einer Abfragekomponente sind die Zeichen ";", "/", "?", ":", "@", "&", "=", "+", "," Und "$" Reserviert.

Das erste, was mich verwirrt, ist, dass * uric so definiert ist

uric = reserved | unreserved | escaped

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

Dies wird jedoch durch Absätze wie z

Die obige "reservierte" Syntaxklasse bezieht sich auf diejenigen Zeichen, die in einem URI zulässig sind, in einer bestimmten Komponente der generischen URI-Syntax jedoch möglicherweise nicht zulässig sind. Sie werden als Begrenzer der in Abschnitt 3 beschriebenen Komponenten verwendet.

Zeichen im "reservierten" Satz sind nicht in allen Kontexten reserviert. Der tatsächlich in einer bestimmten URI-Komponente reservierte Zeichensatz wird von dieser Komponente definiert. Im Allgemeinen ist ein Zeichen reserviert, wenn sich die Semantik des URI ändert, wenn das Zeichen durch seine maskierte US-ASCII-Codierung ersetzt wird.

Dieser letzte Auszug fühlt sich etwas rückwärts an, aber er besagt eindeutig, dass der reservierte Zeichensatz vom Kontext abhängt. 3.4 besagt jedoch, dass alle reservierten Zeichen innerhalb einer Abfragekomponente reserviert sind. Das einzige, was die Semantik hier ändern würde, ist das Entkommen des Fragezeichens (?), Da URIs das Konzept einer Abfragezeichenfolge nicht definieren.

Zu diesem Zeitpunkt habe ich die RFCs vollständig aufgegeben, fand RFC 1738 jedoch besonders interessant.

Eine HTTP-URL hat folgende Form:

http://<host>:<port>/<path>?<searchpart>

Innerhalb der Komponenten <path> und <searchpart> "/", ";", "?" sind reserviert. Das Zeichen "/" kann in HTTP verwendet werden, um eine hierarchische Struktur zu bestimmen.

Ich interpretiere dies zumindest in Bezug auf HTTP-URLs, die RFC 1738 anstelle von RFC 2396 verwendet. Da die URI-Abfrage keine Vorstellung von einer Abfragezeichenfolge hat, kann ich bei der Interpretation von reservierten auch nicht wirklich Abfragezeichenfolgen definieren, wie ich es gewohnt bin jetzt tun.

Frage

Dies alles begann, als ich eine Liste von Nummern zusammen mit der Anfrage einer anderen Ressource übergeben wollte. Ich habe nicht viel darüber nachgedacht und es nur als durch Kommas getrennte Werte übergeben. Zu meiner Überraschung wurde das Komma jedoch entfernt. Die page.html?q=1,2,3verschlüsselte Abfrage page.html?q=1%2C2%2C3funktioniert, ist aber hässlich und hat es nicht erwartet. Zu diesem Zeitpunkt habe ich angefangen, RFCs durchzugehen.

Meine erste Frage ist einfach: Ist das Codieren von Kommas wirklich notwendig?

Meine Antwort laut RFC 2396: Ja, gemäß RFC 1738: Nein

Später fand ich verwandte Beiträge zum Weitergeben von Listen zwischen Anfragen. Wo der CSV-Ansatz als schlecht eingestuft wurde. Dies zeigte sich stattdessen (habe dies noch nicht gesehen).

page.html?q=1;q=2;q=3

Meine zweite Frage, ist das eine gültige URL?

Meine Antwort gemäß RFC 2396: Nein, gemäß RFC 1738: Nein (; ist reserviert)

Ich habe keine Probleme mit der Übergabe von CSV, solange es sich um Zahlen handelt, aber ja, Sie laufen Gefahr, Werte hin und her codieren und decodieren zu müssen, wenn das Komma plötzlich für etwas anderes benötigt wird. Wie auch immer, ich habe die Semikolon-Abfragezeichenfolge mit ASP.NET ausprobiert und das Ergebnis war nicht das, was ich erwartet hatte.

Default.aspx?a=1;a=2&b=1&a=3

Request.QueryString["a"] = "1;a=2,3"
Request.QueryString["b"] = "1"

Ich sehe nicht, wie sehr sich dies von einem CSV-Ansatz unterscheidet, da ich bei der Frage nach "a" eine Zeichenfolge mit Kommas erhalte. ASP.NET ist sicherlich keine Referenzimplementierung, hat mich aber noch nicht enttäuscht.

Aber am wichtigsten - meine dritte Frage - wo ist die Spezifikation dafür? und was würdest du tun oder was nicht?

John Leidegren
quelle
Wie kann RFC 1738 RFC 2396 ersetzen, als RFC 2396 fast 4 Jahre später veröffentlicht wurde?
Matthew Flaschen
1
In Bezug auf URLs und was praktisch Sinn macht, ist es meine Interpretation, die es tut. (Ersetzen ist jedoch wahrscheinlich nicht das richtige Wort, da RFC 1738 in der RFC-Terminologie für veraltete alte RFCs nicht mehr als veraltet empfunden wird, wenn es die einzige Spezifikation ist, die es Ihnen ermöglicht, eine Abfragezeichenfolge in das Suchteil einzufügen der URL)
John Leidegren

Antworten:

68

Dass ein Zeichen in einer generischen URL-Komponente reserviert ist, bedeutet nicht, dass es maskiert werden muss, wenn es in der Komponente oder in Daten in der Komponente angezeigt wird. Das Zeichen muss auch als Trennzeichen innerhalb der generischen oder schemaspezifischen Syntax definiert sein und das Erscheinungsbild des Zeichens muss innerhalb der Daten liegen.

Der aktuelle Standard für generische URIs ist RFC 3986 , der Folgendes zu sagen hat:

2.2. Reservierte Zeichen

URIs umfassen Komponenten und Unterkomponenten, die durch Zeichen im "reservierten" Satz begrenzt sind. Diese Zeichen werden als "reserviert" bezeichnet, da sie durch die generische Syntax, durch jede schemaspezifische Syntax oder durch die implementierungsspezifische Syntax des Dereferenzierungsalgorithmus eines URI als Begrenzer definiert werden können (oder auch nicht). Wenn Daten für eine URI-Komponente mit dem Zweck eines reservierten Zeichens als Trennzeichen in Konflikt stehen würden [Hervorhebung hinzugefügt], müssen die widersprüchlichen Daten vor der Bildung des URI prozentual codiert werden.

   reserviert = Gen-Delims / Sub-Delims

   gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@"

   sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
               / "*" / "+" / "," / ";" / "="

3.3. Pfadkomponente

[...]
pchar = nicht reserviert / pct-codiert / sub-delims / ":" / "@"
[...]

3.4 Abfragekomponente

[...]
      query = * (pchar / "/" / "?")

Daher sind Kommas in Abfragezeichenfolgen explizit zulässig und müssen nur dann in Daten maskiert werden, wenn bestimmte Schemata dies als Trennzeichen definieren. Das HTTP-Schema verwendet kein Komma oder Semikolon als Trennzeichen in Abfragezeichenfolgen, sodass sie nicht maskiert werden müssen. Ob Browser diesem Standard folgen, ist eine andere Frage.

Die Verwendung von CSV sollte für Zeichenfolgendaten problemlos funktionieren. Sie müssen lediglich die Standard-CSV-Konventionen befolgen und entweder Daten in Anführungszeichen setzen oder Kommas mit umgekehrten Schrägstrichen umgehen.

RFC 2396 ermöglicht auch nicht entkoppelte Kommas in HTTP-Abfragezeichenfolgen:

2.2. Reservierte Zeichen

Viele URI enthalten Komponenten, die aus bestimmten Sonderzeichen bestehen oder durch diese begrenzt sind. Diese Zeichen werden als "reserviert" bezeichnet, da ihre Verwendung innerhalb der URI-Komponente auf ihren reservierten Zweck beschränkt ist. Wenn die Daten für eine URI-Komponente mit dem reservierten Zweck in Konflikt stehen würden, müssen die widersprüchlichen Daten vor der Bildung des URI maskiert werden.

Da Kommas im HTTP-Schema keinen reservierten Zweck haben, müssen sie nicht in Daten maskiert werden. Der Hinweis aus § 2.3 über reservierte Zeichen, die die Semantik ändern, wenn sie prozentual codiert sind, gilt nur allgemein. Zeichen können prozentual codiert werden, ohne die Semantik für bestimmte Schemata zu ändern, und sind dennoch reserviert.

outis
quelle
23

Um zu beantworten, was in einer Abfragezeichenfolge gültig ist, habe ich überprüft, welche Sonderzeichen bei einer Anfrage durch Chrome ersetzt werden:

Space -> %20
! -> !
" -> %22
# -> removed, marks the end of the query string
% -> %
& -> &
' -> %27
( -> (
) -> )
* -> *
+ -> + (this usually means blank when received at the server, so encode if necessary)
, -> ,
- -> -
. -> .
/ -> /
: -> :
; -> ;
< -> %3C
= -> =
> -> %3E
? -> ?
@ -> @
[ -> [
\ -> \
] -> ]
^ -> ^
_ -> _
` -> `
{ -> {
| -> |
} -> }
~ -> ~

Extended ASCII (like °) -> Every character from this set is encoded

Hinweis: Das bedeutet wahrscheinlich nicht, dass Sie Zeichen nicht entkommen sollten, die beim Generieren von URIs für Links nicht ersetzt wurden. Beispielsweise wird häufig empfohlen, die Verwendung ~in URIs aufgrund von Kompatibilitätsproblemen nicht zu verwenden , es handelt sich jedoch weiterhin um ein gültiges Zeichen.

Ein anderes Beispiel wäre das Pluszeichen, das gültig ist, aber normalerweise als codiertes Leerzeichen behandelt wird, wenn ein Server es als Teil einer Anforderung empfängt. Daher sollte es auch dann codiert werden, wenn es gültig ist, wenn es ein Plus und kein Leerzeichen darstellen soll.

Um zu beantworten, was codiert werden soll: Ungültige Zeichen und Zeichen, die Sie wörtlich behandeln möchten, aber eine besondere Bedeutung haben oder auf Serverseite Probleme verursachen können.

user764754
quelle
Ist /programming/2366260/whats-valid-and-whats-not-in-a-uri-query?param=b#1;c#2ein gültiger Abfrageparameter?
Sumit Jain
@SumitJain Nein, da #der Abfrageteil eines URI nicht unverändert angezeigt werden kann. Sie müssen es als codieren %23, damit URI sein sollte /programming/2366260/whats-valid-and-whats-not-in-a-uri-query?param=b%231;c%232.
Dai
10

Benutz einfach ?q=1+2+3

Ich beantworte hier eine vierte Frage :), die nicht gestellt wurde, aber alles begann mit: Wie übergebe ich eine Liste von Zahlen mit durch Kommas getrennten Werten? Mir scheint, der beste Ansatz besteht darin, sie durch Leerzeichen zu trennen, wobei Leerzeichen in URL-Form codiert werden +. Funktioniert hervorragend, solange Sie wissen, dass die Werte in der Liste keine Leerzeichen enthalten (etwas, was Zahlen normalerweise nicht tun).

Nas Banov
quelle
Dies sollte zwar ein Kommentar sein (da er die Frage nicht beantwortet), aber danke. +macht in dem speziellen Fall, in dem ich ein Komma verwenden wollte, noch mehr Sinn.
Gajus
6

page.html? q = 1; q = 2; q = 3

Ist das eine gültige URL?

Ja. Das ;ist reserviert, aber nicht von einem RFC. Der Kontext, der diese Komponente definiert, ist die Definition des application/x-www-form-urlencodedMedientyps, der Teil des HTML-Standards ist (Abschnitt 17.13.4.1 ). Insbesondere die in Abschnitt B.2.2 versteckte hinterhältige Notiz :

Wir empfehlen, dass HTTP-Server-Implementierer und insbesondere CGI-Implementierer die Verwendung von ";" anstelle von "&", um den Autoren die Mühe zu ersparen, "&" Zeichen auf diese Weise zu entkommen.

Leider unterstützen viele gängige serverseitige Skript-Frameworks, einschließlich ASP.NET, diese Verwendung nicht.

Bobince
quelle
Während die ?q=1;q=2;q=3Abfrage gültig ist, ist sie nicht eindeutig: Einige serverseitige Frameworks lesen sie so { q: '1;q=2;q=3' }, andere bedeuten dies möglicherweise ähnlich { q: {'1', '2', '3'}}.
Nas Banov
1
Ja. Und was noch schlimmer ist, HTML5 enthält jetzt nicht die Sprache, über ;die HTML4 und HTML5 inkonsistent sind. Ugh, die Gefahren der nicht normativen Sprache in einem Spezifikationsdokument ...
seit dem
@ NasBanov Und noch andere (zB PHP) werden es interpretieren als{ q: 3 }
Nicholas Shanks
1
@NicholasShanks - wo PHP beteiligt ist, sind alle Wetten aus! :)
Nas Banov
1

Ich möchte darauf hinweisen, dass dies auch page.html?q=1&q=2&q=3eine gültige URL ist. Dies ist eine völlig legitime Methode, um ein Array in einer Abfragezeichenfolge auszudrücken. Ihre Servertechnologie bestimmt, wie genau dies dargestellt wird.

In Classic ASP überprüfen Sie Response.QueryString("q").Countund verwenden dann Response.QueryString("q")(0)(und (1) und (2)).

Beachten Sie, dass Sie dies auch in Ihrem ASP.NET gesehen haben (ich denke, es war nicht beabsichtigt, aber schauen Sie):

Default.aspx?a=1;a=2&b=1&a=3

Request.QueryString["a"] = "1;a=2,3"
Request.QueryString["b"] = "1"

Beachten Sie, dass das Semikolon ignoriert wird. Sie haben es aalso zweimal definiert und den Wert zweimal durch Komma getrennt erhalten. Die Verwendung aller kaufmännischen Und-Zeichen Default.aspx?a=1&a=2&b=1&a=3ergibt a"1,2,3". Ich bin mir jedoch sicher, dass es eine Methode gibt, um jedes einzelne Element abzurufen, falls die Elemente selbst Kommas enthalten. Es ist einfach die Standardeigenschaft des nicht indizierten QueryString, die die Unterwerte zusammen mit Komma-Trennzeichen verkettet.

ErikE
quelle
1

Ich hatte das gleiche Problem. Die mit einem Hyperlink versehene URL war eine URL eines Drittanbieters und erwartete page.html?q=1,2,3NUR eine Liste von Parametern im Format, und die URL page.html?q=1%2C2%2C3funktionierte nicht. Ich konnte es mit Javascript zum Laufen bringen. Möglicherweise nicht der beste Ansatz, aber Sie können die Lösung hier überprüfen, wenn sie jemandem hilft.

Schrägstrich
quelle
-3

Wenn Sie die ENCODED-Zeichen an die FLASH / SWF- Datei senden , sollten Sie das Zeichen zweimal ENCODIEREN !! (wegen Flash Parser)

T.Todua
quelle