J’ai interdit les chaînes de requête
(chrismorgan.info)- Chris Morgan a décidé de bloquer totalement les chaînes de requête non autorisées sur son site, et l’implémentation actuelle se trouve dans le Caddyfile
- Il ne veut pas que des paramètres de suivi comme
?ref=example.comsoient ajoutés à ses URL, estimant que, si besoin, il suffit de consulter l’en-tête Referer - Il considère que les UTM parameters comme
?utm_source=example&utm_*&c.*sont destinés à être utilisés par le propriétaire du site, et non ajoutés depuis l’extérieur - Son site n’utilise actuellement aucune chaîne de requête et, s’il en utilise plus tard, il prévoit de n’autoriser que les paramètres connus
- L’URL finale retenue est
/no-query-strings, et il n’a pas choisi/%3Fen raison d’un problème avec la réécrituretry_filesde Caddy
Blocage des chaînes de requête non autorisées
- Chris Morgan a décidé de bloquer totalement les chaînes de requête non autorisées sur son site
- Il ne veut pas que des paramètres de suivi comme
?ref=example.comsoient ajoutés à ses URL, estimant que, si besoin, il suffit de consulter l’en-têteReferer - Il considère que les UTM parameters comme
?utm_source=example&utm_*&c.*sont destinés à être utilisés par le propriétaire du site, et non ajoutés depuis l’extérieur - Ce site n’utilise actuellement aucune chaîne de requête et, s’il en utilise plus tard, il prévoit de n’autoriser que les paramètres connus
- Par le passé, il utilisait des URL d’invalidation de cache de type
?t=…,?h=…pour les feuilles de style, mais il estime acceptable que ce type de requêtes ne fonctionne plus - Ce blocage est actuellement implémenté dans le Caddyfile
Choix de l’URL
-
Le projet d’utiliser
/?- Au départ, la tentation était forte de publier cette page à l’adresse
https://chrismorgan.info/? - Avec un chemin vide et une requête vide, cette forme aurait remis en cause beaucoup d’hypothèses courantes mais erronées, et aurait pu mettre certains outils en difficulté
curlsemblait supprimer à tort le point d’interrogation final en ligne de commande, et l’utilisation via des bibliothèques n’a pas été testée- Il a finalement décidé de respecter la notion de chemin et de se montrer plus indulgent envers les gens, d’autant plus qu’il estimait déjà pousser Caddy dans une direction suffisamment inconfortable
- Au départ, la tentation était forte de publier cette page à l’adresse
-
Le projet d’utiliser
/%3F- Le plan suivant était de publier à
/%3F, où le chemin est?et la requête est absente - Mais il y avait un problème dans Caddy lorsqu’une réécriture
try_filesentrait en jeu - Le ticket associé est :
try_filescasse les chemins contenant des caractères comme?et%
- Le plan suivant était de publier à
-
Choix final
- L’URL finale retenue est
/no-query-strings /?ou/%3Fpourraient être utilisés plus tard pour un autre usage lié aux chaînes de requête
- L’URL finale retenue est
1 commentaires
Commentaires sur Hacker News
Comme ça m’intriguait, je suis retourné voir les standards W3C de HTML et des URL, et contre toute attente, le format des chaînes de requête n’y est pas défini autrement que par le percent-encoding
On peut confondre une chaîne de requête avec une chaîne de requête « form-urlencoded »[0], mais ce n’est qu’un des formats interopérables possibles. En général, une chaîne de requête est simplement une chaîne arbitraire encodée en pourcentage après le
?d’une URL[1], et c’est une autre propriété de l’objet HTMLURLqui peut être utilisée pour générer la réponseL’objet
URLSearchParamsest le résultat du parsing de la chaîne de requête par un parseur form-urlencoded, mais ce n’est qu’une couche d’interopérabilité pour JavaScriptFranchement, avant de relire les standards, j’étais prêt à défendre l’avis inverse, mais ils sont assez clairs. Répondre par 404 à une chaîne de requête inattendue peut aussi être approprié. Une chaîne de requête fait autant partie de l’API d’une URL que le chemin, et la plupart des gens peuvent admettre qu’ajouter arbitrairement une chaîne au chemin n’est pas une bonne idée et relève d’un comportement non défini
[0]: https://url.spec.whatwg.org/#application/x-www-form-urlencod...
[1]: https://url.spec.whatwg.org/#url-class
index.phpet gèrent tout le routage via la chaîne de requêteBien sûr, c’était au format form-urlencoded, les gens n’étaient pas des barbares. On voyait donc des URL comme
index.php?p=home,index.php?p=shopouindex.php?action=showthread&forum=42&thread=17976. Avec une structure comme ça, il devient immédiatement évident que répondre 404 à un paramètre de requête inconnu est logiqueEn réalité, beaucoup de sites fonctionnent encore ainsi aujourd’hui, simplement cachés derrière quelques règles de réécriture Apache/nginx pour le SEO
Au final, une URL n’est qu’une chaîne de caractères que le serveur décide d’interpréter comme il veut
Ce qui est vraiment drôle dans cette discussion, c’est que tout le monde s’inquiète des effets de bord d’une réponse en 404 tout en oubliant complètement combien longtemps, dans l’histoire du web, les chemins ont été dépourvus de sens. Aujourd’hui, le chemin a gagné. On ne repart presque plus de zéro avec des URL du type
/item?id=…. Tant mieux !Ça se lit comme « corrigez votre requête et réessayez », et c’est aussi comme ça que je procède dans l’API que je fournis. Je préfère cela à 406 parce que le problème n’est pas que mon côté ne peut pas le traiter. Si vous avez essayé de casser quelque chose en ajoutant des éléments à la chaîne de requête, ou si vous n’avez pas construit la requête comme documenté, c’est la responsabilité du demandeur
https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/...
Par exemple, du point de vue du cache,
url?a=b&c=dpeut être considéré comme équivalent àurl?c=d&a=bIl existe énormément de conventions qui n’ont jamais été documentées comme standards officiels, mais dont l’absence de respect casse beaucoup de choses, et aussi beaucoup de « standards » qu’il serait idiot de suivre à la lettre
Dans le cas du billet original, les seuls à en subir les conséquences sont les personnes qui essaient de visiter le site, et elles cliqueront probablement simplement sur le bouton retour de leur navigateur pour passer à autre chose. À chacun de décider si ce niveau de nuisance est acceptable. Mais ce n’est pas parce qu’aucun standard ne l’interdit que c’est autorisé par définition, et inversement, ce n’est pas parce qu’un standard l’interdit que cela devient soudainement inadmissible
Si j’ai bien compris, il semble surtout agacé par le fait que d’autres sites web ajoutent une chaîne de requête du type
?ref=origin.comaux liens pointant vers son siteJe ne vois pas bien quel avantage cela apporte au site d’origine ni quel tort cela cause au site de l’auteur
Le comportement des deux côtés me paraît complètement confus
Quand on gère des campagnes publicitaires, je comprends que Google ajoute des chaînes UTM pour suivre depuis quelle campagne les utilisateurs arrivent. Dans ce cas, la source et la destination coopèrent. Mais ici, la source ajoute quelque chose sans raison apparente. Pourquoi ?
ref, qu’un trafic important vient dexyz.com, il pourrait envisager d’y acheter de la publicité ou de nouer un partenariatHonnêtement, pour des sites de niche ou de startup, c’est assez utile. J’ai vu les deux côtés de conversations lancées à partir de ce type de valeur dans les analytics web : une fois, c’est moi qui ai contacté l’autre partie après avoir vu le trafic entrant ; une autre fois, c’est le site vers lequel je faisais un lien qui m’a contacté. Dans les deux cas, cela s’est terminé par des partenariats bénéfiques pour tout le monde
Je comprends aussi, dans une certaine mesure, l’argument sur la vie privée, mais cela ne fournit pas plus d’informations que l’en-tête standard
Referer. C’est juste beaucoup plus visible si l’on utilise des outils d’analyse comme Simple Analytics ou PlausibleL’ajout de chaînes de requête sert souvent au suivi. Le simple fait qu’il existe des fonctionnalités comme « copy clean link » dans Firefox ou Enhanced Tracking Protection, qui supprime préventivement certains paramètres UTM, montre bien que beaucoup de gens n’en veulent pas
Certains sites acceptent volontiers de participer à ce que j’appelle un peu vite « l’économie du suivi », parce que le destinataire peut voir dans ses logs qu’un grand nombre de visiteurs vient de leur site et agir d’une manière qui leur soit favorable
Refuser les chaînes de requête est une simple protestation contre ce système
En lisant la description, « une petite console web décentralisée, auto-hébergée, permettant aux visiteurs de découvrir des sites et pages intéressants recommandés par une communauté indépendante de gestionnaires de sites personnels », je me suis dit qu’avant on appelait ça un Webring. Ce n’était simplement pas formulé de façon aussi grandiloquente
L’un des problèmes que j’avais rencontrés en développant un framework d’application open source, c’est qu’avec certains hébergements utilisant FastCGI, l’en-tête
Authn’était pas respecté, si bien qu’on n’avait pas d’autre choix que de faire passer le token dans la requête. C’était vraiment pénible, parce qu’en copiant/collant une adresse web, le token se retrouvait souvent inclus. C’est peut-être corrigé aujourd’huiSur les backends que je contrôle et qui n’ont pas besoin d’être exposés à tout le monde, j’utilise des en-têtes
Auth?Je serais curieux d’avoir plus de détails là-dessus. Techniquement, ça ressemble à dire qu’un enregistrement
PARAMne fournit pas réellement la valeur attendueIl dit : « J’ai donc décidé d’essayer une interdiction générale sur ce site : aucune chaîne de requête non approuvée », mais son site semble renvoyer 414 si une requête contient une chaîne de requête, et à mon avis c’est un mauvais choix
Si cette protestation vise à défendre les utilisateurs, pourquoi punir ceux qui, au départ, ne contrôlaient probablement même pas cette chaîne ?
Ne vaudrait-il pas mieux s’en servir comme signal pour expliquer aux utilisateurs comment prendre eux-mêmes cette décision, via des outils du navigateur ou autre ?
400 Bad Request, bon code d’erreur client générique, mais pas drôle
402 Payment Required, honnêtement je suis ouvert à l’idée si quelqu’un me paie pour que certaines URL avec chaîne de requête fonctionnent
404 Not Found, mais c’est trop susceptible de produire des effets de bord et ça ne transmet pas le ressenti “le format de la requête est mauvais” que je recherche
303 See Other sans en-tête
Location. C’est très rare de nos jours, mais légitime. En tout cas, ça l’était dans la RFC 2616 (“The different URI SHOULD be given by the Location field in the response”). Mais dans les RFC 7231 et 9110, la formulation a changé de façon à présupposer la présence de l’en-têteLocation(“… as indicated by a URI in the Location header field”). En revanche, 301, 302, 307 et 308 disent “the server SHOULD generate a Location header field”. Quoi qu’il en soit, je pense qu’un See Other sans en-têteLocationreste tout à fait acceptable. Mais URI Too Long était plus drôle »https://chrismorgan.info/no-query-strings?foo
À la phrase « On peut prétendre que j’abuse de 414 URI Too Long. Ma réponse est que c’est plus drôle comme ça. Les autres options que j’avais envisagées étaient… », on pourrait aussi proposer 418 I'm a teapot comme autre option. Après tout, les théières ne prennent généralement pas en charge les chaînes de requête
Plusieurs options paraissent adaptées à première vue, mais ne le sont pas vraiment quand on y regarde de plus près : 406 « Not Acceptable » concerne les en-têtes de négociation de contenu, 409 « Conflict » est surtout utilisé pour les requêtes WebDAV, et 411, 422, 431 visent aussi des conditions spécifiques sans rapport avec le sujet
Les erreurs des séries 300 ou 500 seraient elles aussi inappropriées. Ici, on n’a ni redirection ni échec côté serveur, mais un problème de requête côté client
La théière ou l’URI trop longue semblent être les meilleures candidates
À lire ce billet et celui de Chris, on a l’impression que le fait d’inclure ce type de paramètres de requête est nuisible, mais je ne comprends pas en quoi
Je comprends que cela puisse casser certaines URL, et en soi c’est déjà une bonne raison de ne pas le faire. Mais ça me semble être une gêne mineure. Quelqu’un pourrait-il m’expliquer ?
Du point de vue du purisme technique, même si c’est toléré par convention, modifier une URL reste techniquement incorrect. Une URL devrait fondamentalement être traitée comme une valeur opaque
Du point de vue social, c’est du suivi, et les fils de commentaires voisins l’expliquent déjà très bien, donc je ne vais pas répéter
Du point de vue du bruit, cela masque la partie de l’URL qui intéresse réellement l’utilisateur et contribue à rendre les URL si longues et compliquées que les gens ordinaires n’y prêtent plus attention
Referer, tu comprendras pourquoi les gens n’aiment pas ça : https://en.wikipedia.org/wiki/HTTP_refererIl y a de nombreuses raisons de ne pas vouloir qu’un site sache où l’on se trouvait avant d’y arriver. En pratique, c’est partager son historique de navigation avec le site que l’on visite
C’est pour cela qu’il y a eu de nombreuses évolutions autour de l’en-tête HTTP
Referer, notamment des restrictions sur les conditions d’envoi et la possibilité de le désactiver complètementAjouter la même information sous forme de paramètre d’URL contourne ces règles et ces possibilités de refus. Il faudrait simplement utiliser le standard
C’est une posture ridiculement extrême, et elle n’explique pas correctement en quoi cela mènerait à un meilleur web
Ce second point est peut-être plus difficile à comprendre, mais dans mon cas, je ne veux absolument pas que des informations susceptibles de nuire aux utilisateurs restent dans les logs
Personnellement, quand je veux copier un lien pour l’envoyer dans un message et que je me retrouve avec un code de suivi deux fois plus long que l’URL d’origine, ça m’agace vraiment. Soit je dois le supprimer à la main, soit je laisse le destinataire face à tout un écran de caractères aléatoires en se demandant ce que c’est
Cela porte atteinte à la vie privée des utilisateurs, dégrade l’expérience utilisateur, et surtout, personne ne l’a demandé
Comme la source d’origine n’avait encore jamais été discutée sur HN, j’ai mis ce lien (https://chrismorgan.info/no-query-strings) tout en haut et déplacé le lien vers le billet de réponse (https://susam.net/no-query-strings.html) dans le texte d’introduction
Les deux sont bien, mais il me semble plus juste de donner la priorité à l’original
Dans mon coin, la plupart des sites qui utilisent encore des requêtes GET de ce type sont des sites de recouvrement fiscal gérés par des collectivités locales, qui se passent les variables dans tous les sens après la connexion
En réalité, les parseurs de routage qui font exactement la même chose qu’une requête GET tout en prétendant être de vraies URL sont encore plus agaçants
Les chaînes de requête sont utiles. C’est le cas pour la recherche de fichiers ou d’autres types de fichiers dynamiques, mais il ne faut pas les ajouter à des URL qui ne s’attendent pas à en recevoir
Donc refuser des requêtes auxquelles on a ajouté des éléments comme UTM me paraît justifié
Si une chaîne de requête n’était pas prévue mais qu’elle est présente, 404 me semble la réponse la plus cohérente, même si 400 peut aussi convenir