Ich habe Query-Strings verboten
(chrismorgan.info)- Chris Morgan hat beschlossen, auf seiner Website unerlaubte Query-Strings vollständig zu blockieren; die aktuelle Implementierung steht in der Caddyfile
- Er möchte nicht, dass Tracking-Parameter wie
?ref=example.coman seine URLs angehängt werden, und meint, bei Bedarf könne man stattdessen den Referer-Header ansehen - UTM parameters wie
?utm_source=example&utm_*&c.*seien aus seiner Sicht für die Nutzung durch den Website-Betreiber gedacht und nichts, was Außenstehende anhängen sollten - Derzeit verwendet die Website überhaupt keine Query-Strings; falls sich das später ändert, will er nur bekannte Parameter zulassen
- Als endgültige URL hat er
/no-query-stringsgewählt;/%3Fkam wegen Problemen mit Caddystry_files-Rewriting nicht infrage
Unerlaubte Query-Strings blockieren
- Chris Morgan hat beschlossen, auf seiner Website unerlaubte Query-Strings vollständig zu blockieren
- Er möchte nicht, dass Tracking-Parameter wie
?ref=example.coman seine URLs angehängt werden, und meint, bei Bedarf könne man stattdessen denReferer-Header ansehen - UTM parameters wie
?utm_source=example&utm_*&c.*seien aus seiner Sicht für die Nutzung durch den Website-Betreiber gedacht und nichts, was Außenstehende anhängen sollten - Derzeit verwendet diese Website überhaupt keine Query-Strings; falls sich das später ändert, will er nur bekannte Parameter zulassen
- Früher nutzte er Cache-Invalidierungs-URLs in Form von
?t=…und?h=…für Stylesheet-URLs, hält es aber für akzeptabel, wenn solche Anfragen jetzt kaputtgehen - Diese Sperre ist derzeit in der Caddyfile implementiert
Prozess bei der URL-Auswahl
-
Plan,
/?zu verwenden- Anfangs war die Versuchung groß, diese Seite unter
https://chrismorgan.info/?zu veröffentlichen - Als Form aus leerem Pfad und leerer Query hätte das viele verbreitete, aber falsche Annahmen aufgebrochen und einige Tools in Schwierigkeiten gebracht
curlschien auf der Kommandozeile das abschließende Fragezeichen unzulässigerweise zu entfernen; die Verwendung über Bibliotheken hat er nicht getestet- Letztlich entschied er sich, das Konzept eines Pfads zu respektieren und den Leuten entgegenzukommen, zumal er Caddy seiner Meinung nach ohnehin schon weit genug in eine unbequeme Richtung gedrängt hatte
- Anfangs war die Versuchung groß, diese Seite unter
-
Plan,
/%3Fzu verwenden- Der nächste Plan war, die Seite unter
/%3Fzu veröffentlichen, also mit einem Pfad von?und ohne Query - Allerdings gab es in Caddy ein Problem, das die Verarbeitung verhinderte, sobald
try_files-Rewriting beteiligt war - Das zugehörige Issue lautet:
try_filesbeschädigt Pfade mit Zeichen wie?und%
- Der nächste Plan war, die Seite unter
-
Endgültige Wahl
- Als endgültige URL wurde
/no-query-stringsfestgelegt /?oder/%3Fkönnten später noch für andere Zwecke rund um Query-Strings verwendet werden
- Als endgültige URL wurde
1 Kommentare
Hacker-News-Kommentare
Aus Neugier habe ich noch einmal die W3C-Standards für HTML und URL nachgeschlagen, und überraschenderweise ist das Format von Query-Strings dort abgesehen von der Prozentkodierung nicht weiter definiert.
Man kann Query-Strings mit „form-urlencoded“[0]-Query-Strings verwechseln, aber das ist nur eines von mehreren interoperablen Formaten. Im Allgemeinen ist ein Query-String einfach eine beliebige prozentkodierte Zeichenfolge[1] nach dem
?in der URL und eine weitere Eigenschaft des HTML-URL-Objekts, die zur Erzeugung einer Antwort verwendet werden kann.Das
URLSearchParams-Objekt ist das Ergebnis des Parsens eines Query-Strings mit einem form-urlencoded-Parser, aber das ist nur eine Interoperabilitätsschicht für JavaScript.Ehrlich gesagt war ich vor dem Blick in die Standards bereit, zu widersprechen, aber die Standards sind ziemlich eindeutig. Es kann also angemessen sein, auf unerwartete Query-Strings mit 404 zu antworten. Query-Strings sind genauso Teil der URL-API wie Pfade, und die meisten würden wohl zustimmen, dass es keine gute Idee ist, beliebige Zeichenfolgen an einen Pfad anzuhängen, und dass das undefiniertes Verhalten ist.
[0]: https://url.spec.whatwg.org/#application/x-www-form-urlencod...
[1]: https://url.spec.whatwg.org/#url-class
index.phpzu haben und das gesamte Routing über den Query-String abzuwickeln.Natürlich im form-urlencoded-Format, die Leute waren ja keine Barbaren. Deshalb gab es URLs wie
index.php?p=home,index.php?p=shopoderindex.php?action=showthread&forum=42&thread=17976. In so einer Struktur ist sofort klar, dass 404 die richtige Antwort auf unbekannte Query-Parameter ist.Tatsächlich funktionieren auch heute noch viele Websites so und verstecken es nur wegen SEO hinter ein paar Apache-/nginx-Rewrite-Regeln.
Am Ende ist eine URL nur eine Zeichenfolge, bei der der Server entscheidet, wie er sie verarbeitet.
Das wirklich Lustige an dieser Diskussion ist, dass man sich über die Nebenwirkungen einer 404-Antwort Sorgen macht, dabei aber völlig vergessen hat, wie lange Pfade in der Geschichte des Webs bedeutungslos waren. Inzwischen hat sich der Pfad durchgesetzt. Kaum jemand startet heute noch neu mit URLs wie
/item?id=…. Schön so!Das liest sich eher als „korrigiere die Anfrage und versuche es erneut“, und so nutze ich es auch in der API, die ich anbiete. Ich bevorzuge das gegenüber 406, weil es kein Problem ist, das ich nicht verarbeiten kann. Wenn jemand etwas an den Query-String angehängt hat, um etwas kaputtzumachen, oder die Anfrage nicht gemäß der Dokumentation aufgebaut hat, dann liegt die Verantwortung beim Anfragenden.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/...
Aus Sicht des Cachings kann man zum Beispiel
url?a=b&c=dundurl?c=d&a=bals identisch betrachten.Es gibt viele Konventionen, die nie als offizielle Standards dokumentiert wurden, aber bei Nichtbeachtung weitreichende Brüche verursachen, und es gibt viele „Standards“, bei denen man sich dumm anstellt, wenn man sie wörtlich befolgt.
Im Fall des ursprünglichen Beitrags sind die einzigen Leidtragenden die Leute, die diese Website besuchen wollten, und die werden vermutlich einfach im Browser auf „Zurück“ klicken und weitermachen. Ob man diesen Schaden in Kauf nimmt, kann jede Person selbst entscheiden. Nur weil kein Standard etwas verbietet, ist es nicht automatisch per Definition erlaubt, und umgekehrt wird etwas nicht plötzlich unzulässig, nur weil ein Standard es verbietet.
So wie ich es verstehe, war der Autor wohl genervt davon, dass andere Websites an Links zu seiner Seite Query-Strings wie
?ref=origin.comanhängen.Ich verstehe nicht, welchen Vorteil das für die Ursprungsseite und welchen Schaden es für die Seite des Autors haben soll.
Das Verhalten beider Seiten wirkt völlig verwirrend.
Wenn man Werbekampagnen fährt, ist nachvollziehbar, dass Google UTM-Query-Strings anhängt, um zu verfolgen, aus welcher Kampagne ein Nutzer kam. In dem Fall arbeiten Ausgangs- und Zielseite zusammen. Hier aber hängt die Ausgangsseite ohne ersichtlichen Grund etwas an. Warum?
ref-Query-String sieht, dass viel Traffic vonxyz.comkommt, und dann vielleicht dort Werbung schaltet oder eine Partnerschaft eingeht.Ehrlich gesagt ist das für Nischen-/Startup-Seiten ziemlich nützlich. Ich habe beide Seiten solcher Gespräche erlebt, die durch solche Werte in der Webanalyse ausgelöst wurden: Einmal habe ich mich wegen eingehenden Traffics gemeldet, ein anderes Mal wurde ich von einer Seite kontaktiert, auf die ich verlinkt hatte. In beiden Fällen endete es in einer für beide Seiten vorteilhaften Partnerschaft.
Ich verstehe auch bis zu einem gewissen Grad die Datenschutzargumente, aber es liefert nicht mehr Informationen als der standardmäßige
Referer-Header. Wenn man Analysetools wie Simple Analytics oder Plausible nutzt, fällt es nur viel stärker auf.Das Anhängen von Query-Strings wird häufig für Tracking verwendet. Schon die Existenz von Funktionen wie „copy clean link“ in Firefox oder Enhanced Tracking Protection, das einige UTM-Parameter proaktiv entfernt, zeigt, dass viele Menschen das nicht wollen.
Manche Websites beteiligen sich bereitwillig an einem System, das ich locker als „Tracking-Ökonomie“ bezeichnen würde. Der Empfänger kann in den Logs sehen, dass viele Menschen von seiner Website kommen, und dann etwas tun, das dieser Website nützt.
Query-Strings abzulehnen ist ein einfacher Protest gegen dieses System.
Als ich die Beschreibung las — „eine kleine, dezentrale, selbst gehostete Web-Konsole, mit der Besucher interessante Websites und Seiten erkunden können, die von der Community unabhängiger Betreiber persönlicher Websites empfohlen werden“ — dachte ich: Früher nannte man so etwas Webring. Nur nicht ganz so geschniegelt.
Eines der Probleme, die ich bei der Entwicklung eines Open-Source-Anwendungs-Frameworks hatte, war, dass Hosting mit FastCGI den
Auth-Header nicht beachtete, sodass ich Token als Query übergeben musste. Beim Kopieren und Einfügen von Webadressen landeten dadurch häufig Token mit drin, was wirklich übel war. Vielleicht ist das inzwischen behoben.In Backends, die ich kontrolliere und die nicht für alle öffentlich sein müssen, verwende ich Header.
Auth-Header kaputtgemacht hat?Mich würde interessieren, ob du das näher erklären kannst. Technisch klingt das so, als würde der
PARAM-Datensatz nicht den erwarteten Wert liefern.Dort steht: „Also habe ich versucht, auf dieser Site ein generelles Verbot durchzusetzen: keine nicht genehmigten Query-Strings“, aber seine Website scheint bei Anfragen mit Query-String 414 zurückzugeben, und ich halte das für die falsche Wahl.
Wenn dieser Protest die Nutzer verteidigen soll, warum bestraft man dann Nutzer für etwas, das sie von vornherein womöglich gar nicht kontrollieren konnten?
Wäre es nicht besser, das als Signal zu nutzen und den Nutzern zu zeigen, wie sie diese Entscheidung selbst treffen können, etwa über Browser-Tools?
400 Bad Request, als allgemeiner Client-Fehlercode passend, aber langweilig
402 Payment Required, ehrlich gesagt wäre ich offen dafür, wenn jemand dafür bezahlen würde, dass bestimmte URLs mit Query-String funktionieren
404 Not Found, aber das hat zu leicht zu viele Nebenwirkungen und vermittelt nicht das von mir beabsichtigte Gefühl von ‚falschem Anfrageformat‘
303 See Other ohne
Location-Header. Heute extrem selten, aber legitim. Zumindest in RFC 2616 war das so („The different URI SHOULD be given by the Location field in the response“). In 7231 und 9110 wurde das jedoch so geändert, dass die Existenz einesLocation-Headers vorausgesetzt wird („… as indicated by a URI in the Location header field“). Im Gegensatz dazu sagen 301, 302, 307 und 308: „the server SHOULD generate a Location header field“. Wie auch immer, ich halte ein See Other ohneLocation-Header weiterhin für ausreichend legitim. Aber URI Too Long war lustiger.“https://chrismorgan.info/no-query-strings?foo
Bei der Stelle „Man könnte behaupten, ich missbrauche 414 URI Too Long. Meine Antwort lautet: So ist es lustiger. Andere Optionen, die ich erwogen habe, waren …“ könnte man als weitere Option auch 418 I'm a teapot in Betracht ziehen. Teekannen unterstützen schließlich normalerweise auch keine Query-Strings.
Es gibt einige Optionen, die passend wirken, es bei näherem Hinsehen aber nicht sind: 406 „Not Acceptable“ basiert auf Content-Negotiation-Headern, 409 „Conflict“ ist vor allem für WebDAV-Anfragen gedacht, und 411, 422, 431 beziehen sich ebenfalls auf bestimmte Bedingungen, die hier nicht passen.
Fehler aus dem 300er- oder 500er-Bereich sind auch ungeeignet. Es geht hier nicht um Umleitung oder serverseitiges Versagen, sondern um ein Problem mit der Client-Anfrage.
Die besten Kandidaten scheinen also Teekanne oder zu lang zu sein.
Beim Ton dieses Beitrags und von Chris’ Beitrag wirkt es so, als sei das Einfügen solcher Query-Parameter schädlich, aber ich verstehe nicht, wie genau.
Ich verstehe, dass manche URLs dadurch kaputtgehen können, und allein das ist schon ein guter Grund, es nicht zu tun. Trotzdem wirkt es wie eine eher kleine Unannehmlichkeit. Kann das jemand erklären?
Aus Sicht des technischen Purismus ist das Verändern einer URL technisch falsch, selbst wenn es konventionsgemäß akzeptiert wird. URLs sollten grundsätzlich als opake Werte behandelt werden.
Aus sozialer Sicht ist es Tracking, und die benachbarten Kommentarstränge erklären das schon gut genug, daher wiederhole ich es nicht.
Aus Sicht des Lärms trägt es dazu bei, die Teile zu verdecken, die Nutzer tatsächlich beachten müssen, und URLs so schwierig und komplex zu machen, dass normale Menschen sich gar nicht mehr für URLs interessieren.
Referer-Header ansieht, versteht man, warum Leute das nicht mögen: https://en.wikipedia.org/wiki/HTTP_refererEs gibt viele Gründe, warum man nicht möchte, dass eine Website erfährt, wo man war, bevor man sie erreicht hat. Im Grunde teilt man der besuchten Site seinen Browserverlauf mit.
Deshalb gab es für den HTTP-
Referer-Header viele Aktualisierungen, etwa Einschränkungen für die Übermittlung und die Möglichkeit, die Funktion komplett abzuschalten.Wenn man dieselben Informationen stattdessen als URL-Parameter anhängt, umgeht man diese bestehenden Regeln und Opt-out-Möglichkeiten. Man sollte einfach den Standard verwenden.
Das ist eine absurd extreme Haltung, und es wird nicht überzeugend erklärt, wie das zu einem besseren Web führen soll.
Letzteres ist vielleicht schwerer nachzuvollziehen, aber ich persönlich möchte absolut nicht, dass in meinen Logs Informationen landen, die Nutzern schaden könnten.
Ich hasse es auch, wenn ich einen Link kopieren und in eine Nachricht einfügen will und daran dann ein Tracking-Code hängt, der doppelt so lang ist wie die eigentliche URL. Dann muss ich ihn entweder von Hand entfernen oder den Empfänger mit einem Bildschirm voller zufälliger Zeichen ratlos zurücklassen.
Es verletzt die Privatsphäre der Nutzer, sorgt für eine schlechte Nutzererfahrung und vor allem hat niemand darum gebeten.
Da die Originalquelle auf HN offenbar noch nicht diskutiert worden war, habe ich diesen Link (https://chrismorgan.info/no-query-strings) ganz nach oben gesetzt und den Link zum Antwortbeitrag (https://susam.net/no-query-strings.html) in die Top-Beschreibung verschoben.
Beide sind gut, aber es wirkt fair, dem Original den Vorrang zu geben.
Die meisten Sites hier in der Gegend, die noch GET-Queries verwenden, sind von Kommunen betriebene Steuereinzugsseiten, die nach dem Login Variablen hin- und herschieben.
Tatsächlich nerven mich Routing-Parser, die im Grunde dasselbe tun wie GET-Anfragen, aber so tun, als wären sie echte URLs, noch viel mehr.
Query-Strings sind nützlich. Etwa für Dateisuche oder andere Arten dynamischer Dateien, aber man sollte sie nicht an URLs anhängen, die keine Query-Strings erwarten.
Deshalb halte ich es für richtig, Anfragen mit angehängten Dingen wie UTM abzulehnen.
Wenn ein Query-String nicht erwartet wird, aber trotzdem vorhanden ist, scheint mir 404 als Antwort am sinnvollsten, wobei 400 ebenfalls angemessen sein könnte.