1 points par GN⁺ 5 시간 전 | 1 commentaires | Partager sur WhatsApp
  • 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.com soient 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 /%3F en raison d’un problème avec la réécriture try_files de 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.com soient 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
  • 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é
    • curl semblait 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
  • Le projet d’utiliser /%3F

  • Choix final

    • L’URL finale retenue est /no-query-strings
    • /? ou /%3F pourraient être utilisés plus tard pour un autre usage lié aux chaînes de requête

1 commentaires

 
GN⁺ 5 시간 전
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 HTML URL qui peut être utilisée pour générer la réponse
    L’objet URLSearchParams est 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 JavaScript
    Franchement, 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

    • Autrefois, il était assez courant que des CMS ou des forums n’aient qu’un seul index.php et gèrent tout le routage via la chaîne de requête
      Bien 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=shop ou index.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 logique
      En 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
    • Oui, une URL n’a pas tant de sémantique que ça. Il semble bien y avoir une intention selon laquelle le chemin sert à des données hiérarchiques et la requête à des données non hiérarchiques, il existe de fortes conventions, et certaines sont prises en charge voire imposées par des bibliothèques, mais il n’y a pas de vraie règle
      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 !
    • Je me demande si un 400 générique ne serait pas préférable. La page n’est pas introuvable, c’est la requête envoyée qui n’est pas autorisée
      Ç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
    • La proposition No-Vary-Search permet d’indiquer quelles parties de la requête sont pertinentes
      https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/...
      Par exemple, du point de vue du cache, url?a=b&c=d peut être considéré comme équivalent à url?c=d&a=b
    • Un standard n’est jamais que le comportement largement accepté que quelqu’un, quelque part, a fini par écrire
      Il 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.com aux liens pointant vers son site
    Je 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 ?

    • Du point de vue du site d’origine, c’est du marketing. L’idée est que si l’auteur voit, dans la chaîne de requête ref, qu’un trafic important vient de xyz.com, il pourrait envisager d’y acheter de la publicité ou de nouer un partenariat
      Honnê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 Plausible
    • Je suis globalement opposé au suivi. Le suivi va en général à l’encontre de l’intérêt des individus
      L’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
    • Si un site populaire ajoute ce paramètre, le site cible peut facilement savoir qui lui envoie du trafic, et cela peut servir de base à des sponsorisations ou à des accords d’affiliation
  • 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 Auth n’é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’hui
    Sur 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

    • Tu as écrit le framework d’application open source en fcgi-app, et tu veux dire que, par exemple, Apache cassait l’en-tête Auth ?
      Je serais curieux d’avoir plus de détails là-dessus. Techniquement, ça ressemble à dire qu’un enregistrement PARAM ne fournit pas réellement la valeur attendue
  • Il 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 ?

    • « 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 les suivantes :
      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ête Location (“… 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ête Location reste tout à fait acceptable. Mais URI Too Long était plus drôle »
      https://chrismorgan.info/no-query-strings?foo
    • C’est ancien et mes souvenirs sont flous, mais j’ai l’impression qu’il existait une version de pages serveur PLSQL qui renvoyait 500 lorsqu’on lui passait une chaîne de requête inconnue
  • À 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

    • De simples 400 « Bad Request » ou 403 « Forbidden » me semblent aussi des choix défendables. C’est étrange qu’il n’existe pas de code d’erreur dédié aux paramètres d’URI
      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
    • Bien sûr que si, elles les prennent en charge. On peut par exemple interroger le niveau d’eau de la théière en descendant le fil, ou interroger sa circonférence en enroulant le fil autour
    • Mais moi, je ne suis pas une théière. Je n’aime pas le thé
  • À 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 ?

    • Il y a trois angles de lecture
      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
    • Si tu lis ce qu’il y a autour de l’en-tête HTTP Referer, tu comprendras pourquoi les gens n’aiment pas ça : https://en.wikipedia.org/wiki/HTTP_referer
      Il 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ètement
      Ajouter 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
    • Il n’y a absolument aucune raison. Il suffit de jeter cette information
      C’est une posture ridiculement extrême, et elle n’explique pas correctement en quoi cela mènerait à un meilleur web
    • Ce qui est intéressant, c’est qu’aucun de ces sites ne semble disposer d’une fonction de recherche. Or la recherche est une fonctionnalité d’accessibilité importante et un cas d’usage clair et légitime des chaînes de requête
    • Il y a plusieurs raisons. Les utilisateurs n’ont pas consenti à être suivis, et ce type de paramètre de requête constitue une information de suivi. Par ailleurs, l’administrateur du site peut ne pas vouloir que le trafic entrant soit traqué
      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