David Madore's WebLog: Vulgarisation informatique : comment fonctionne le Web ?

[Index of all entries / Index de toutes les entréesLatest entries / Dernières entréesXML (RSS 1.0) • Recent comments / Commentaires récents]

↓Entry #2755 [older| permalink|newer] / ↓Entrée #2755 [précédente| permalien|suivante] ↓

(mardi)

Vulgarisation informatique : comment fonctionne le Web ?

Avant-propos

Pour changer un peu des entrées portant sur des maths incompréhensibles, j'ai voulu essayer de faire de la vulgarisation informatique et à un niveau — j'espère ! — compréhensible par tout le monde, pour expliquer les principes de base de comment fonctionne le World Wide Web (ce que la plupart des gens appellent Internet, mais ci-dessous je vais expliquer entre autres choses la différence entre ces termes).

Enfin, du moins, c'était mon idée initiale en commençant à écrire ce billet, mais il a, comme d'habitude, enflé bien au-delà de ce que j'imaginais possible, m'a demandé un temps totalement déraisonnable, et qui s'est plutôt transformé en un tas d'explications disparates (parfois à la limite du rant) sur divers sujets pas reliés de façon très cohérente les uns aux autres (et si certains sont, je l'espère, effectivement compréhensibles par tout le monde, il est clair qu'à d'autres endroits j'ai raté mon pari). Et j'avoue franchement que le plan de ce billet est complètement incohérent (par exemple, ce passage ne devrait pas être relégué à une sous-sous-sous-partie). La bonne nouvelle, c'est que tous ces petits bouts sont assez largement indépendants les uns des autres, donc on doit pouvoir lire ce pavé en sautant — ou en lisant en diagonale — les passages qu'on trouve inintéressants ou incompréhensibles, ou en picorant les passages potentiellement intéressants. Pour essayer d'aider le lecteur à lire en diagonale, j'ai fait précéder les parties et sous-parties d'un bref résumé de ce qui s'y dit (signalé par le signe ‘❖’).

Bon, j'avoue aussi ma crainte d'avoir essentiellement perdu mon temps à déployer des efforts pédagogiques mais que, au final, les gens qui me lisent savent déjà tout et n'apprendront rien, tandis que ceux qui ne savent pas déjà tout se diront que ce sont des questions hautement techniques qui ne les intéressent pas du tout et n'auront pas envie de me lire. Mais je pense que les gens qui se disent que ce sont des questions hautement techniques se trompent, et je pense que l'essentiel de ce que je vais raconter ci-dessous constitue des connaissances extrêmement basiques que tout le monde devrait avoir avant d'ouvrir un navigateur Web, histoire de ne pas risquer de tomber dans le premier hameçonnage venu (ah ben j'ai suivi le lien dans le mail, ça ressemblait bien au site de ma banque, donc j'ai donné mon mot de passe), du coup je fais l'effort de me dire que ça vaut la peine que je prenne la peine de l'écrire, au risque de pisser très longuement dans un violon.

Si au moins quelqu'un apprend quelque chose, n'hésitez pas à dire quoi en commentaire (ou d'ailleurs, à l'inverse, si vous trouvez que c'est trop technique et que ça n'a aucun intérêt, dites moi surtout à quel point vous avez laissé tomber), ça m'intéresse aussi d'en faire une sorte de petit sondage pour savoir si écrire ce genre de billet de vulgarisation a un sens.

Je vais faire beaucoup d'efforts pour garder mes explications au niveau le plus bas possible (et encore une fois, là où je n'y arrive pas, faites-le moi savoir, mon but est aussi d'apprendre à expliquer !). Du coup, fatalement, je vais parfois dire des choses qui sont un peu approximatives ou simplifiées (mais j'espère jamais complètement fausses, et je vais essayer de toujours dire que je simplifie) : je précise ça parce que je soupçonne que beaucoup de gens qui me liront seront, en fait, des gens déjà parfaitement compétents et qui vont plutôt avoir tendance à me chercher des poux. (Ceci vaut pour toute tentative de vulgarisation, bien sûr, mais particulièrement ici parce que je tâche de rester bien plus compréhensible que ce que je raconte d'ordinaire.)

Ce qui a déclenché mon envie d'écrire tout ça, ce n'est pas vraiment des questions de sécurité et de hameçonnage, c'est plutôt que Twitter et Reddit ont, à peu près au même moment, décidé de fermer leur API publique et gratuite, je trouve cette évolution très préoccupante (même si elle n'est pas du tout surprenante de la part du douchebro qui a repris Twitter), et je pense que ça a un sens d'expliquer de quoi il est question (c'est quoi, une API publique ?) et d'essayer de donner du contexte sur les enjeux d'ouverture du web. En plus de ça, pendant que j'étais en train d'écrire ce billet, je suis tombé sur cet article de Ars Technica sur la Web Integrity de Google, et j'ai inséré quelque chose à ce sujet.

Mais ces questions-là viendront à la fin : commençons plutôt par le début, c'est-à-dire par les définitions de base de ce que sont Internet et le Web et les très grandes lignes de leur fonctionnement.

Table des matières

Liste des termes définis dans le texte

(Liste donnée dans l'ordre dans lequel les termes sont définis ou évoqués pour la première fois. Chacun est un lien vers cette première définition ou évocation. Le terme apparaît en gras dans le texte à l'endroit lié.)

C'est quoi Internet ? C'est quoi le Web ? Et c'est quoi la différence ?

Dans cette section, je définis l'Internet (réseau d'ordinateurs interconnectés) et le Web (réseau d'information sous forme de pages hypertexte et reliées les unes aux autres par des hyperliens). J'évoque le fonctionnement « client-serveur » du Web et le protocole HTTP (au-dessus d'Internet) central à son fonctionnement, ainsi que le format HTML dans lequel sont écrites les pages hypertexte.

Je dois d'abord définir ce qu'est le Web et quelques termes en rapport avec lui, et contraster avec Internet.

Alors d'abord, le Web n'est pas pareil qu'Internet. Internet c'est un réseau d'ordinateurs interconnectés (en gros, de nos jours, tous les ordinateurs du monde) qui leur permet de s'échanger des informations. (Cela se fait au moyen d'un jeu de protocoles de communication appelé TCP/IP, qu'on peut donc considérer pour simplifier comme synonyme d'Internet, et qui a été inventé entre le milieu des années 1970 et le début des années 1980, essentiellement dans le cadre de recherches financées par le Département de la Défense américain, je ne rentre pas dans plus de détails, voyez Wikipédia si vous voulez en savoir plus. Mais ça vaut la peine de mentionner au moins deux noms de gens qui ont joué un rôle central dans la création de ces protocoles : Vinton Cerf et Bob Kahn, souvent considérés comme les pères d'Internet.)

Le but de ce billet n'est pas d'expliquer comment fonctionne Internet. Ce serait éventuellement pour une autre fois, mais je vais tenir Internet pour acquis.

Le (World Wide) Web, abrégé WWW, i.e. la Toile mondiale, c'est (ou au moins c'était, à l'origine) une manière d'utiliser Internet pour mettre à disposition des informations sous forme de pages Web. Une page Web peut contenir du texte, des images, des sons, des vidéos ou autres animations (et maintenant des programmes complets, je vais y revenir), et surtout, elle peut contenir des hyperliens, ou simplement liens, qui pointent vers d'autres pages Web (permettant à l'utilisateur de passer facilement de l'une à l'autre), l'ensemble de tout ça étant appelé de l'hypertexte. Enfin, je suppose que vous savez ça, parce que si vous lisez ces mots, a priori (sauf si par exemple vous êtes une personne du futur en train de lire une archive de quelques textes ayant miraculeusement survécu à l'apocalypse — auquel cas, coucou, et content de avoir que des bouts de mon blog en font partie), vous savez au moins un peu ce qu'est une page Web puisque vous êtes en train d'en lire une.

Le Web fonctionne au-dessus d'Internet (c'est-à-dire qu'il dépend d'Internet pour fonctionner), selon un mécanisme dit client-serveur : d'un côté il y a l'ordinateur de la personne qui veut lire une page Web, qu'on appelle client : il utilise un programme spécial, appelé navigateur Web, pour consulter le Web et afficher les pages hypertexte : ce programme côté client va contacter la machine qui met la page à disposition, et qu'on appelle le serveur (et qui fait tourner lui aussi un programme spécial, appelé serveur Web — parfois ce terme désigne la machine, parfois le programme, ce n'est pas toujours clair, et souvent pas très important) pour lui demander. La communication a lieu via Internet, c'est-à-dire que le client et le serveur doivent déjà faire partie d'Internet (avoir un accès Internet) pour espérer communiquer. Elle a lieu, plus précisément, par un protocole appelé HTTP (ou sa variante chiffrée, HTTPS dont je parlerai plus bas) qui se place au-dessus des protocoles TCP/IP : imaginez que TCP/IP est comme la poste qui achemine des lettres, alors que HTTP est un formulaire que vous envoyez pour recevoir un livre. Quant au format dans lequel les pages Web sont écrites s'appelle HTML (bon, là je simplifie excessivement, et je vais y revenir), qui est en gros une façon de décrire le contenu (là il y a le texte suivant, là il y a un hyperlien vers telle adresse, là il y a une image dont voici l'adresse).

Le Web a été inventé en gros une décennie après Internet, entre la fin des années 1980 et le début des années 1990, essentiellement au CERN (le Centre européen pour la recherche nucléaire, basé en Suisse), là aussi je renvoie à Wikipédia pour plus de détails, mais il y a un nom qui revient généralement comme le père du Web : Tim Berners-Lee (avec, comme dans le cas d'Internet, le caveat important qu'une invention de ce genre n'est jamais le fruit d'une seule personne et que c'est toujours réducteur de donner un seul nom ou même deux). Il y avait d'autres mécanismes utilisant Internet pour diffuser de l'information générale inventés avant ou à peu près au même moment (par exemple Gopher, qui est maintenant presque mais pas complètement mort, plus simple, utilisant une structure organisée en menus hiérarchiques ; ou FTP, qui joue un rôle un peu différent, puisque c'est plutôt pour échanger des fichiers entre ordinateurs qu'à destination d'un humain, mais il est lui aussi quasiment remplacé par HTTP(S) de nos jours), mais le Web a eu tellement de succès qu'il est devenu quasiment synonyme d'Internet.

Ce n'est pas qu'une confusion du grand public de traiter ces deux termes (Web et Internet) comme presque interchangeables, c'est de plus en plus vrai que beaucoup de systèmes d'échanges de données, même ceux qui concerne pas des pages hypertexte ou même qui ne sont pas des données à afficher directement à un humain dans un navigateur, tendent à utiliser le protocole HTTP(S) initialement prévu pour le Web, et que du coup les contours de ce dernier deviennent un peu flous. Mais c'est aussi et surtout le cas que le navigateur Web devient de plus en plus une sorte d'« application universelle », c'est-à-dire que toutes sortes de services de toutes sortes (communication, bureautique, jeux, etc.) tournent optionnellement ou même exclusivement à l'intérieur d'un navigateur Web, ce qui entretient la confusion non seulement entre le Web et l'Internet mais même entre le navigateur Web et l'ensemble du système d'exploitation (je veux dire que beaucoup de gens ne font sans doute pas une distinction claire entre une « Web application » qui tourne à l'intérieur de leur navigateur web, et un programme distinct du navigateur qui tourne sur leur ordinateur, et c'est encore pire sur les téléphones mobiles ; je reparlerai des Web applications plus bas pour essayer de dissiper cette confusion).

Malgré cette tendance à confondre Web et Internet, il continue à exister un grand nombre de protocoles Internet, plus ou moins spécialisés, qui ne peuvent pas vraiment être considérés comme faisant partie du Web. (Y compris des protocoles utilisés par le grand public : à titre d'exemple, BitTorrent, un protocole de partage de fichiers décentralisé et pair-à-pair, c'est-à-dire que tout le monde s'échange des petits bouts de fichier sans que personne n'ait une copie autoritative, notamment souvent utilisé pour partager des vidéos dites « pirates », c'est-à-dire échangées en contravention du droit d'auteur, est basé sur Internet mais s'oppose radicalement à l'organisation client-serveur du Web. De même, les applications de vidéoconférence comme Zoom ou Skype utilisent leurs propres protocoles propriétaires au-dessus d'Internet, même s'il y a souvent une passerelle Web permettant de les utiliser depuis un navigateur Web.)

En revanche, tous les réseaux sociaux (Facebook, Twitter, Instagram, Reddit, StackExchange, TikTok, etc.) peuvent être décrits comme faisant partie du Web ou construits au-dessus de lui : même s'ils disposent d'une application spécialisée permettant d'éviter de passer par un navigateur Web généraliste, ils restent toujours consultables via un navigateur Web, i.e., ils ont toujours au moins une interface Web en plus d'éventuelles interface mobile (essentiellement Android et iOS) vers le même contenu (je ne sais pas pourquoi, ça semble être uniquement sur mobile qu'on propose ces applications spécialisée, alors qu'il n'y a pas vraiment de raison technique pour laquelle on ne pourrait pas avoir une appli spécialisée pour ordinateur pour accéder à chacun de ces réseaux sociaux — l'explication relève plus de considérations historiques ou sociologiques que techniques).

Le fonctionnement de base du Web à papa

Dans cette section, j'évoque les idées essentielles fonctionnement du Web des années 1990–2000, en parcourant les composantes d'une adresse Web ou URL : nom d'hôte puis nom de chemin.

Comme je le dis ci-dessus, le Web est devenu quelque chose d'assez protéiforme, non seulement presque synonyme d'Internet mais englobant même presque tout ce qui se fait sur un ordinateur, et je pense que cela contribue à la confusion que le grand public peut ressentir. Pour dissiper cette confusion, je pense qu'il vaut mieux commencer par décrire le « Web à papa », c'est-à-dire le Web des années 1990–2000 (en gros), quand il s'agissait vraiment de consulter des pages de texte avec des hyperliens et quelques images et pas de faire essentiellement tout et n'importe quoi jusqu'à ne plus savoir ce qui est sur notre ordinateur et ce qui est dans un cloud vaporeux.

Remontons le temps et replaçons-nous donc dans cette époque où les choses étaient un peu plus simples. Vous voulez consulter une page Web (ou un ensemble de pages Web apparentées : un site Web). D'abord, vous lancez un programme spécial, le navigateur Web. Je vais revenir sur les navigateurs Web et leur histoire, mais tenons-les pour acquis pour le moment. Dedans, vous tapez, dans la barre d'adresse (parce qu'à l'époque il n'y a pas vraiment de moteur de recherche), l'adresse de la page que vous voulez consulter : on parle aussi d'URL ou URI pour cette adresse (il y a une petite différence entre ces deux termes, les URI étant plus générales que les URL, mais ignorons cette subtilité byzantine : les adresses de type HTTP sont bien des URL et donc aussi des URI). Cette adresse peut ressembler à quelque chose comme :

http://www.example.tld/some/where.html

Ceci signifie approximativement : se connecter (au moyen du protocole HTTP) à l'ordinateur serveur ayant le nom www.example.tld sur Internet, et lui demander le fichier ayant pour nom /some/where.html.

Mais donnons quelques explications un peu plus précises à ce sujet.

D'abord, la partie www.example.tld est vraiment un nom d'ordinateur, ou, comme on dit dans le jargon, un nom d'hôte (hostname) : c'est le nom du serveur web de l'institution qui héberge la page qu'on veut consulter. Le premier serveur web devait avoir un nom du genre info.cern.ch parce que le CERN est en Suisse, dont le domaine national est .ch, donc il a le domaine .cern.ch (je vais venir au fonctionnement de ces domaines dans un instant), et la machine s'appelle info dans ce domaine. Plus tard est venue la convention d'appeler www la machine qui servait de serveur Web dans n'importe quel domaine, d'où des noms comme www.example.tld : mais c'était (et d'ailleurs, c'est toujours) juste une convention sur le nommage des machines ; puis, quand le Web est devenu beaucoup plus commercial, on s'est dit que les gens ne voulaient pas avoir à taper des adresses compliquées comme http://www.departement.institution.tld/secteur/nom-de-produit.html donc les gens se sont mis à créer en masse des sites avec des noms simples à mémoriser comme www.le-produit-en-question.com (voire tout simplement le-produit-en-question.com) et les utilisateurs avaient juste à taper ça dans leur navigateur, le navigateur ajoutant le http:// automatiquement devant (et un / derrière) et le site est plus facilement accessible à un truc qu'on peut mettre sur une affiche dans le métro. Mais même dans un nom comme ça, www.le-produit-en-question.com et reste un nom d'ordinateur (en général il a plein de noms différents, cf. plus bas) qu'on contacte pour avoir la page.

La partie /some/where.html derrière, c'est le nom ou chemin du fichier demandé au serveur. Le caractère ‘/’ est utilisé, ici, parce que c'est le séparateur de répertoires dans le système d'exploitation Unix : sous Unix, comme sur tous les systèmes d'exploitations qui ont suivi, les fichiers sont organisés en arborescence, c'est-à-dire qu'ils sont regroupés en répertoires (un répertoire étant en gros un sac contenant des fichiers), eux-mêmes regroupés en répertoires et ainsi de suite jusqu'à un répertoire appelé répertoire racine qui contient tout. Sous Unix, un fichier du genre /home/david/personal/journal.txt signifie que dans le répertoire racine il faut chercher le répertoire home (qui contient typiquement les répertoires personnels des utilisateurs, au moins sous un Unix moderne), dans celui-ci le sous-répertoire david, dedans le sous-répertoire personal et dedans le fichier journal.txt (la convention est que le fichier a souvent un nom contenant un ‘.’ suivi d'une extension qui indique le type du fichier ; mais c'est une convention plus qu'autre chose) : c'est ça qu'on appelle un chemin. Ceci étant, comme je vais le dire, même dans le Web à papa, le serveur Web n'est pas obligé d'utiliser dans les URL qu'il sert les chemins exacts des fichiers de son arborescence Unix ; mais simplifions autant que possible pour commencer.

Bref, dans le Web à papa (et les mécanismes fondamentaux en sont toujours valables aujourd'hui), vous tapez quelque chose comme http://www.example.tld/some/where.html dans votre navigateur, celui-ci initie une connexion (de type TCP/IP) avec le serveur www.example.tld et commence à lui parler en HTTP. De l'autre côté, c'est-à-dire sur l'ordinateur www.example.tld, il y a un autre programme (le pendant du navigateur), le serveur Web, qui attend qu'on le contacte et qu'on lui parle en HTTP pour envoyer les fichiers qu'on lui demande.

Il y a un autre élément d'adresse que je peux mentionner parce qu'on le rencontre parfois, c'est un port TCP : l'adresse prend alors la forme http://www.example.tld:8080/some/where.html où le nombre 8080 est un numéro de port. Sans vouloir expliquer comment fonctionne le protocole TCP, disons juste que c'est une façon d'avoir plusieurs serveurs Web sur la même machine (et le même nom de machine) : le port 80 est le port normal en HTTP (en HTTPS c'est 443), et si on ne l'écrit pas dans l'adresse c'est la valeur par défaut (donc si on tape http://www.google.com/ ou http://www.google.com:80/ c'est la même chose), mais le port 8080 (ou en HTTPS, 8443) reste une valeur alternative fréquente. Dans tous les cas cette valeur n'a pas de sens particulier, c'est juste une sorte de boîte aux lettres interne sur l'ordinateur, que l'administrateur du serveur a choisi d'utiliser.

Je ne vais pas entrer dans les détails du protocole HTTP, mais le navigateur va envoyer une requête qui ressemble à quelque chose comme GET /some/where.html HTTP/1.0 pour dire renvoie-moi une copie du fichier /some/where.html que tu as, et en réponse il reçoit normalement le fichier en question (avec un « code de retour » 200 OK qui signifie tout s'est bien passé, et voici le résultat ; mais il y a plein d'autres possibilités de codes de retour dont la plus célèbre est 404 Not Found qui signifie je n'ai pas ou ne connais pas ce fichier, qui peut être accompagné d'une erreur personnalisée). Le serveur renvoie aussi un type de contenu du fichier, et quand il s'agit d'un fichier HTML (ce qui est souvent suggéré par l'extension .html dans le nom, mais ça n'a rien d'obligatoire), signalé par le type de contenu text/html, le navigateur va décoder le format HTML et afficher la page en question.

La page en question contiendra peut-être un hyperlien (indiqué dans le HTML) vers une page différente, par exemple http://www.example.tld/else/where.html sur le meme serveur, et dans ce cas, si l'utilisateur clique sur ce lien, le navigateur fait comme si cette URL avait été saisie directement dans la barre d'adresse, et va donc contacter le serveur (ici le même) pour lui demander le fichier en question, et l'afficher. Et ainsi de suite jusqu'à ce que l'utilisateur décide d'arrêter de perdre son temps à lire des pages sans intérêt sur le Web à papa.

Bon, maintenant, expliquons un peu plus précisément certains des points de cette histoire, pour pouvoir aborder les changements qui ont eu lieu depuis.

Nom d'hôte, nom de domaine : le travail du DNS

Dans cette section, je décris le fonctionnement du DNS qui permet de retrouver l'ordinateur à partir de son nom (« nom d'hôte »).

J'ai écrit ci-dessus que si on navigue à l'adresse http://www.example.tld/some/where.html le client (navigateur) va initier une connexion avec la machine www.example.tld : il faut que je précise un peu ce que ça signifie et implique.

Toute machine reliée à Internet a ce qu'on appelle une adresse IP ou abusivement une IP : c'est ce code numérique qui permet de la contacter. (Bon, c'est simplifié, une même machine peut avoir plusieurs adresses IP, c'est fréquemment le cas pour les « routeurs » qui servent justement à envoyer les connexions au bon endroit ; et inversement, plusieurs machines peuvent partager une adresse IP, auquel cas elles ne sont pas contactables séparément, ou seulement à travers des magouilles diverses ; mais au niveau d'explication où je me place, faisons comme si une machine = une adresse IP.)

Par ailleurs, il y a maintenant deux versions du protocole IP qui coexistent, l'ancien IPv4 dont les adresses ressemblent à des choses comme 163.172.82.209 ou 203.0.113.1, c'est-à-dire 4 nombres entre 0 et 255 séparés par des ‘.’, ce qui fait environ 4 milliards de possibilités si on utilisait ça optimalement ce qui n'est évidemment pas le cas, d'où le fait qu'on est en situation de pénurie et qu'il a fallu changer de version ; et le nouveau IPv6 dont les adresses ressemblent à des choses comme 2001:bc8:30e8:200::1 ou 2001:db8:dead:beef::80, les nombres étant écrits en hexadécimal, le séparateur étant ‘:’, et les adresses étant beaucoup plus longues, ce qui fait un nombre faramineux de possibilités. On est en train de transitionner d'IPv4 vers IPv6, donc souvent les ordinateurs ont les deux, l'adresse IPv4 étant généralement partagée pour les machines qui ne sont pas des serveurs : si les deux ordinateurs qui veulent communiquer ont une IPv6, ils vont normalement préférer cette version, sinon, si les deux ont une IPv4 ils vont utiliser ça, sinon ils ne peuvent pas se parler. Mais tout ça n'est pas très important pour ce que je veux raconter.

Une adresse IP, c'est comme un numéro de téléphone : c'est ça qu'il faut vraiment utiliser pour acheminer les données d'un ordinateur à l'autre. Donc le client a besoin de connaître l'adresse IP du serveur avant de commencer à lui parler. Mais un nom comme www.example.tld ce n'est pas la même chose qu'une adresse IP, c'est un nom d'hôte, il est là avant tout pour la commodité des humains. (Parce que s'il est autorisé d'utiliser une adresse IP directement dans une URL, par exemple http://172.217.169.4/ vous renverra bien sur Google, ce n'est vraiment pas commode et on n'a pas envie que les adresses ressemblent à ça, surtout qu'on veut pouvoir changer l'adresse IP d'une machine sans changer tous les liens.)

Il faut donc une sorte d'annuaire téléphonique pour faire la conversion entre le nom d'hôte et l'adresse IP.

Au début d'Internet (avant le Web, donc), il y avait un gros fichier (le fichier des hôtes) partagé par toutes les machines sur Internet et qui donnait la correspondance entre noms et adresses IP (il n'y en avait pas tant que ça, à l'époque, et même ainsi c'est vite devenu ingérable).

Maintenant on utilise un autre système pour faire la correspondance nom → IP, ce système s'appelle le DNS. Je vais dire un mot sur son fonctionnement technique, mais commençons par dire des choses sur la manière dont sont organisés les noms.

La hiérarchie des noms de domaine

Le DNS a un fonctionnement hiérarchique : j'évoque ici la manière dont les noms d'hôtes s'organisent en « domaines » concentriques, et comment ils sont attribués.

Le DNS est un système hiérarchique en partant de la fin, c'est-à-dire qu'une machine ayant le nom www.example.tld est la machine www à l'intérieur du domaine example lui-même à l'intérieur du domaine tld dans le domaine racine. Le domaine racine est celui qui contient tout le DNS, un domaine immédiatement rattaché au domaine racine — comme mon exemple fictif de .tld, mais des exemples plus connus seraient .com ou .fr s'appelle un domaine de premier niveau, et un domaine comme .example.tld s'appelle domaine de second niveau, et ainsi de suite (il n'y a pas de limite sur la profondeur de niveaux, mais il y a une limite sur la longueur totale, et dans la pratique on dépasse rarement trois ou quatre niveaux).

Il s'agit là d'un regroupement purement conventionnel : les machines d'un domaine n'ont pas de raison d'être géographiquement proches, par exemple ; elles ont tendance à être proches en organisation, mais ça n'a rien d'obligatoire (je peux parfaitement décider de donner à une machine chez Google un nom en madore.org si ça me chante, je n'ai pas besoin de leur demander une autorisation). Une machine peut très bien avoir plusieurs noms dans le DNS (ou elle peut n'en avoir aucune, même si c'est mal vu pour toutes sortes de raisons).

Qui a le droit d'enregistrer des noms dans le DNS et comment ? Ça fonctionne de façon hiérarchique. Commençons par expliquer la partie « politique », si j'ose dire. Les domaine de premier niveau ou TLD sont de approximativement deux sortes :

  • Il y en a un par pays (pour une certaine définition de pays, parce que C'est Compliqué®, l'Union européenne est considérée comme un pays dans ce système, et même l'Union soviétique existe encore), qui utilise le code ISO à deux lettres du pays (sauf pour le Royaume-Uni dont le code ISO est GB mais dont le domaine de premier niveau est .uk parce que merci le Club Context), qu'on appelle les domaines nationaux. La gestion des domaines nationaux est confiée aux autorités du pays en question, qui généralement l'ouvrent à l'achat par tout le monde (pour certains pays, comme les Tuvalu dont le domaine national est .tv, c'est même une source importante de revenus parce que les gens s'imaginent que ça veut dire télé), mais parfois ils mettent des conditions de résidence, parfois ils créent des sous-domaines avec des répartitions bien précises (comme .uk où seuls .co.uk et .org.uk semblent vraiment ouverts à tout le monde, tandis que le gouvernement s'est réservé .gov.uk).
  • Les autres sont appelés domaines de premier niveau génériques et… les règles sont différentes pour chacun. Jusqu'à la fin des années 1990, il y avait exactement sept tels domaines : .com, .org, .net (tous les trois ouverts à l'achat par tout le monde, même si en principe .com était destiné aux entités commerciales, .org aux organisations à but non lucratif, et .net aux fournisseurs d'accès eux-mêmes), .int (réservé aux organisations internationales), .edu (réservé aux organisations éducatives en pratique aux États-Unis), .gov (réservé au gouvernement des États-Unis, pas forcément au niveau fédéral) et .mil (réservé spécifiquement à l'armée, la marine et les autres institutions du département de la défense des États-Unis) ; bon, on peut aussi mentionner des trucs maintenant disparus comme .nato et des domaines à usage technique très restreint comme .arpa (en principe il ne devrait pas y avoir de site Web utilisant une adresse en .arpa, mais bien sûr, en vrai il y en a). Maintenant, l'ICANN, l'organisation chargée de gérer le domaine racine et donc de créer les domaines de premier niveau a décidé d'autoriser essentiellement tout et n'importe quoi du moment qu'on paye assez cher, du coup la liste est longue, et plein de grosses organisation peuvent avoir leur vanity TLD dont ils décident les règles (qui doivent quand même être un minimum contrôlées par l'ICANN), par exemple Google a .google pour son usage interne, la Ville de Paris a créé .paris qui est ouvert aux parisiens (et qui n'a pas l'air très populaire, même la Ville de Paris elle-même ne semble pas l'utiliser !) et ainsi de suite. En plus de ça, maintenant, les noms de domaines de premier niveau ne sont plus limités aux caractères latin, même si l'ICANN veille quand même à ce qu'il n'y ait pas de confusion visuelle possible dans les nouveaux domaines de premier niveau créés.

Dans un domaine comme .com, .org, .fr ou .eu, qui est ouvert à tout le monde, la règle est généralement celle du premier arrivé premier servi : n'importe qui peut réclamer n'importe quel nom de domaine qui n'a pas déjà été réclamé, et dans ce cas elle le loue, pour un prix modique (de l'ordre de grandeur d'une dizaine d'euros par an), jusqu'à ce qu'elle décide de le libérer, ou qu'elle oublie de payer, et le domaine redevient disponible (il y a généralement quand même une période de gel pendant laquelle seul le précédent locataire peut réacquérir le domaine en question, pour éviter la ruée sur les oublis de renouvellement de domaines très convoités). Pour les domaines nationaux, il y a parfois une clause selon laquelle le locataire du domaine doit avoir une adresse dans le pays dont le domaine relève (et qui ne sera souvent vérifiée qu'en cas de conflit) ; souvent, il y aussi une clause, explicite ou appliquée par la justice, selon laquelle le propriétaire d'une marque déposée peut réclamer le domaine correspondant à cette marque même s'il est déjà loué. Bref, c'est un peu un chaos de règles mal définies et mal documentées (et il y a plein d'exemples de particuliers qui se sont fait saisir leur domaine par quelqu'un qui avait décidé de déposer la marque correspondant à ce domaine : le cas de milka.fr étant assez célèbre, mais je digresse).

Je ne rentre pas sur la distinction entre le registre (registry) qui gère la liste des sous-domaines du domaine et fixe les règles, maintient l'architecture technique, et le registraire (registrar) qui les vend effectivement, en lien avec le registre (auquel il paie un prix fixe pour l'enregistrement en plus de frais d'accréditation comme registraire), disons juste que c'est un système qui cherche à donner l'illusion d'une concurrence, un peu comme on a séparé le réseau ferroviaire en des gestionnaires de réseau et des opérateurs de trains.

Bien sûr, il y a un business bien établi de cybersquattage dans lequel des sangsues essaient de spéculer sur les domaines qui deviendront intéressants, ou bien reprennent des domaines qui eurent été utilisés et qui ont été remis à la vente (mais il reste des hyperliens qui pointent vers eux), ou bien encore achètent des fautes de frappe fréquentes sur des noms de domaine à énorme trafic (du genre facebok.com), soit pour revendre ces domaines à prix élevé (c'est-à-dire accepter de les libérer en échange d'une somme importante), soit pour y placer de la pub et profiter des liens déjà établis vers ces domaines, soit pour induire les internautes en erreur.

En tout état de cause, une fois qu'on acquiert (i.e., loue) un domaine, on peut techniquement en faire ce qu'on veut : créer n'importe quel nombre de sous-domaines et de noms, et les faire pointer vers n'importe quelle adresse IP ou les déléguer à n'importe qui.

De ce système hiérarchique on tire le corollaire suivant essentiel pour la sécurité : la première chose qu'il faut regarder pour décider quelle confiance on a dans une adresse Web, c'est la fin du nom d'hôte (son nom de domaine).

Exemple pratique : le site officiel du ministère de l'intérieur français est www.interieur.gouv.fr : dès lors qu'on sait que le gouvernement français possède le domaine gouv.fr, on peut faire confiance (enfin, dans la mesure où on fait confiance au gouvernement…) à tout site dont le nom d'hôte se termine en gouv.fr, c'est-à-dire que la partie qui précède immédiatement le premier ‘/’ après le http:// (ou plutôt https://) initial est gouv.fr. Mais attention à ne pas se faire avoir : un nom comme www.interieur-gouv.fr (avec un tiret et pas un point) n'est pas pareil du tout, car il n'est pas dans le domaine gouv.fr, donc a priori n'importe qui peut l'acheter comme n'importe quel domaine en .fr non déjà occuper, et s'en servir pour essayer d'induire les gens en erreur, avec toutes les mauvaises intentions qu'on peut imaginer (y compris mettre une copie exacte du vraie site mais avec de petits changements). Bon, là, précisément, ce site n'existe pas, et on peut espérer que le ministère de l'Intérieur a préventivement acquis ou bloqué l'usage de ce domaine pour éviter les attaques trop évidentes, mais il va de soi qu'on ne peut pas aller au devant de tous les hameçonnages possibles. Il est aussi possible pour une personne mal intentionnée d'acheter le domaine gouv.xx dans un autre domaine dont le nom pourrait causer confusion avec fr, disons par exemple gr (c'est la Grèce), et avoir son propre site www.interieur.gouv.xx là aussi pour faire du hameçonnage.

☞ Une règle de base de la sécurité du Web que tout le monde doit impérativement connaître et comprendre : on ne fait confiance qu'à des adresses qu'on a tapées soi-même et sans faire de faute, ou dont on a suivi un lien depuis une source sûre (p.ex., un lien très haut placé dans un moteur de recherche est raisonnablement sûr ; en revanche, un mail qu'on a reçu est suspect parce qu'il n'y a quasiment aucune vérification de l'origine des mails), et si on n'a qu'une confiance modérée, on regarde bien l'adresse, et spécialement le nom de domaine, pas le contenu de la page (qui peut être arbitrairement falsifié). Le navigateur est votre ami, il ne vous trompera pas sur l'adresse et (sauf bug !) ne permettra pas qu'on vous trompe, par contre le contenu de la page est simplement ce que le serveur de l'adresse en question lui a demandé d'afficher. (J'insiste là-dessus parce que les victimes de hameçonnage ont tendance à ne pas regarder l'adresse, mais, par contre, à regarder si le logo de leur banque est le bon, ce qui est inutile : il est trivial, sur le Web, de reprendre un logo — il n'y a que l'adresse qui peut vous protéger et c'est elle qu'il faut regarder attentivement, et attentivement signifie qu'on repérera bien la différence entre www.interieur.gouv.fr et www.interieur-gouv.fr par exemple.)

Un mot sur la résolution DNS

Je dis ici un mot sur la manière dont s'opère, techniquement, la résolution DNS, c'est-à-dire la conversion entre un nom d'hôte et une adresse IP permettant de contacter la machine.

L'organisation hiérarchique des noms de domaines étant comprise, la conversion d'un nom en adresse IP, ce qu'on appelle la résolution DNS suit la voie hiérarchique assez évidente.

En gros, si je veux connaître l'adresse IP de www.example.tld (et qu'en fait il est plus correct d'écrire www.example.tld. avec un point final, mais on a l'habitude de retirer ce dernier point) :

  • Je commence par contacter un serveur appelé serveur de noms autoritatifs [du domaine] racine (dont je connais l'adresse IP, parce qu'il faut bien commencer quelque part), et je lui demande bonjour, quelles sont les adresses IP des serveurs du domaine tld. ?
  • Je contacte un quelconque des serveurs qu'on m'a indiqués à l'étape précédente (parfois appelé serveur de noms autoritatifs [de domaine] de premier niveau pour le domaine tld.), et je lui demande bonjour, quels sont les adresses IP des serveurs du domaine example.tld. ?
  • Je contacte un des serveurs qu'on m'a indiqués à l'étape précédente, et je lui demande bonjour, quelle est l'adresse IP de l'hôte www.example.tld. ?

La procédure que je viens de décrire s'appelle la résolution DNS, ou plus précisément, la résolution récursive, parce qu'on interroge les serveurs les uns après les autres dans l'ordre hiérarchique. (Il y a évidemment autant d'étapes qu'il y a de points dans le nom. Je glisse évidemment sur plein de subtilités, par exemple s'il y a des serveurs qui défaillent, comment on peut avoir une garantie d'authenticité des résultats, ce qui se passe si une machine a plusieurs adresses, combien de temps les informations sont mémorisées avant d'être redemandées aux serveurs, comment on peut rediriger d'un nom vers un autre, etc.)

Quand j'écris je contacte un serveur […] et je lui demande, ceci utilise un protocole spécifique appelé protocole DNS (et qui fonctionne au-dessus de TCP/IP, enfin, techniquement, souvent UDP/IP mais oublions ce détail) : je ne veux pas en dire plus sur comment il fonctionne, mais l'idée de ce système hiérarchique est que personne n'a besoin de connaître tous les noms de toutes les machines sur Internet, chacun connaît juste sa zone d'autorité. Par exemple, dès lors que j'ai loué le domaine madore.org (auprès d'un registraire de noms de domaines accrédité pour le domaine .org), ce sont mes serveurs qui sont interrogés quand on me demande un nom à l'intérieur de ce domaine, et je peux créer tous les noms de machines ou tous les sous-domaines que je veux à l'intérieur de madore.org (bien sûr, si je n'avais pas voulu m'occuper de la partie technique, j'aurais pu louer, en même temps que le domaine, les services d'un hébergeur de noms de domaine qui aurait fait pour moi la partie technique de fournir les services).

On se doute bien que ce système hiérarchique fait que les serveurs de noms du domaine racine ont un pouvoir extraordinaire, en gros ils contrôlent (à travers leurs délégations et subdélégations aux domaines intermédiaires) les noms de toutes les machines sur Internet. A minima il ne faut pas qu'ils soient victimes d'attaques en déni de service (c'est-à-dire où des millions d'ordinateurs hostiles se coordonneraient pour leur déborder sous les requêtes) : pour cette raison, ils appartiennent à plusieurs organisations différentes, sont hébergés sur des réseaux différents, et sont géographiquement situés sur tous les continents (il y a ostensiblement 13 serveurs DNS racine, étiquetés par les lettres de A à M, gérées par 12 organisations différentes, mais en fait par toutes sortes d'astuces la plupart d'entre eux sont eux-mêmes répartis en une multitude, peut-être une centaine, de machines distinctes : voyez ici pour la carte).

Bon, il y a encore autre chose que je dois dire au sujet de la résolution DNS : en fait, en général, la résolution récursive, c'est-à-dire consistant à interroger un par un les serveurs autoritaires depuis la racine jusqu'au domaine considéré comme je l'ai décrit ci-dessus, ce n'est pas votre ordinateur qui la fait, c'est votre fournisseur d'accès Internet (FAI). Enfin, ça dépend des cas. Votre FAI met certainement à disposition de ses clients un serveur DNS récursif, c'est-à-dire capable de résoudre n'importe quel nom qu'on lui demande (en suivant la procédure récursive décrite ci-dessus, c'est-à-dire en suivant la voie hiérarchique des serveurs autoritaires) : donc le plus souvent, votre ordinateur va simplement demander au serveur récursif proposé par votre FAI quelle est l'IP de www.example.tld et c'est le FAI qui s'occupe (s'il n'a pas déjà la réponse en mémoire) d'aller interroger successivement les serveurs autoritaires du domaine racine, puis du domaine tld et enfin du domaine example.tld.

Ce n'est pas très clair ce qu'on gagne à passer par le serveur du FAI (plutôt que faire soi-même la résolution récursive) : c'est peut-être un peu plus rapide ou moins gourmand en ressources, cela permet de mutualiser la résolution entre clients du même FAI, mais ce sont de petites différences ; et il y a aussi des inconvénients : notamment, quand la justice ordonne aux FAI de « bloquer » un domaine (du genre www.videos-pirates.tld), ce blocage a lieu au niveau DNS, c'est-à-dire que le FAI va renvoyer une erreur (ou une fausse adresse) quand on lui demandera de résoudre un nom dans ce domaine. Que ce soit pour contourner ces blocages ou pour toutes sortes d'autres raisons, on peut vouloir ne pas passer par le serveur DNS du FAI. Une solution évidente dans ce sens est de mener soi-même la résolution récursive (en interrogeant les serveurs autoritaires) : pour ça, il faut installer son propre serveur DNS récursif ; une autre solution est d'interroger des serveurs récursifs mis à disposition du monde entier, notamment 8.8.8.8 qui est fourni par Google ou 1.1.1.1 qui est fourni par CloudFlare (ils ont choisi des IP faciles à mémoriser, puisqu'il faut bien les mémoriser vu que, par définition, on n'a pas de serveur DNS quand on décide de les utiliser), c'est plus simple vu qu'il n'y a qu'un champ à changer dans la configuration du réseau (quelque chose comme serveur de noms). Personnellement je configure mes ordinateurs pour faire eux-mêmes la résolution DNS récursive, mais c'est vrai que mon mobile ne la fait pas (je ne sais pas faire ça sous Android), là je passe par mon FAI (enfin, sur mon wifi personnel c'est quand même mon routeur qui fait la résolution).

Plusieurs noms pour un même serveur

J'évoque ici brièvement le fait qu'une même machine peut avoir beaucoup de noms, et ainsi servir beaucoup de domaines Web différents.

Il y a quelque chose comme deux cents millions de domaines enregistrés dans le seul domaine .com ; j'ai dit plus haut qu'un nom comme www.la-lessive-aspros-lave-plus-blanc-que-blanc.tld est un nom d'ordinateur. Faut-il croire qu'il y a des centaines de millions de serveurs Web, un pour chaque domaine, qui attendent patiemment que quelqu'un s'intéresse au domaine en question ? En fait, non.

Rien n'interdit de faire pointer plusieurs noms différents du DNS vers la même adresse IP, et c'est même ce qui arrive couramment : typiquement, www.la-lessive-aspros-lave-plus-blanc-que-blanc.tld et www.la-lessive-melas-protege-votre-linge-noir.tld (et plein d'autres ; souvent, plein de sites personnels) vont être le même serveur, contacté par la même adresse IP. Oui, mais du coup, comment ce serveur sait-il quel site Web il doit renvoyer si on lui demande le chemin / (qui est celui demandé par défaut si l'utilisateur a juste tapé le nom du domaine dans la barre d'adresse et rien de plus) ? En fait, dans la requête HTTP, le navigateur client indique au serveur non seulement quel chemin il demande mais aussi sous quel nom il a contacté le serveur (ce que le serveur ne peut pas savoir tout seul : lui sait seulement quelle adresse IP a été contactée, pas sous quel nom elle était référencée). Cette astuce évite d'avoir à multiplier les adresses IP (denrée précieuse !, au moins en IPv4) pour multiplier les sites Web. On parle d'hébergement virtuel par le nom (parce qu'on donne l'illusion d'avoir plusieurs serveurs alors qu'il n'y a que le nom qui change).

L'avantage de ce mécanisme est d'économiser les serveurs et les adresse IP. L'inconvénient est qu'il casse une garantie de « transparence référentielle » d'Internet : une machine n'est pas censée avoir connaissance du nom sous lequel on l'a désignée, uniquement de son adresse IP. Normalement, on devrait pouvoir, dans une URL, remplacer la partie « nom d'hôte » par l'adresse IP renvoyée par le DNS. En pratique, très souvent, ça ne marche pas : par exemple, si je tape http://www.elysee.fr/ dans mon navigateur ça m'envoie sur le site de l'Élysée, mais si je demande au DNS quelle est l'adresse IP de www.elysee.fr, j'apprends que c'est 104.18.30.248 (en fait c'est une IP du gros réseau de distribution de contenu Cloudflare), et si je vais à l'adresse http://104.18.30.248/ eh bien j'ai juste une erreur (qui dit d'ailleurs clairement le problème : vous n'avez pas le droit de me contacter par une IP, j'ai besoin d'un nom d'hôte). Vous allez me dire, personne n'a envie de faire ça. Oui mais ça a quand même une conséquence fâcheuse, c'est que si le DNS est en panne (ou bloqué pour un site particulier), même si on a un moyen différent de connaître l'IP d'un site, on ne peut quand même pas le consulter. (Je suis d'avis que les navigateurs devraient prévoir un moyen de contourner le DNS et de dire contacter l'adresse IP suivante en lui affirmant qu'on la contacte sous le nom suivant même si, en fait, cela ne correspond pas à ce qui s'est passé.)

Le travail du serveur Web

Dans cette partie, je me penche sur le travail du serveur Web, la manière dont il renvoie un contenu en réponse à une requête HTTP.

Passons maintenant à la partie chemin de l'adresse Web, c'est-à-dire celle qui suit le nom d'hôte (la partie /some/where.html si l'adresse est http://www.example.tld/some/where.html). Comment le serveur Web choisit-il quel contenu renvoyer ?

Chemin dans l'URL et nom de fichier

Le cas le plus simple est une conversion idiote de la partie « chemin » de l'adresse en un nom de fichier sur le serveur.

J'ai écrit ci-dessus que si on navigue à l'adresse http://www.example.tld/some/where.html le client (navigateur) va demander au serveur www.example.tld le fichier (chemin) /some/where.html et le serveur va le lui retourne : ce n'est pas littéralement vrai. Ne serait-ce que pour des raisons de sécurité et de confidentialité, on n'a évidemment pas envie d'avoir un programme qui, dès qu'on le contacte, accepte de renvoyer le contenu de n'importe quel fichier de l'ordinateur juste parce qu'on lui demande. C'est-à-dire que /some/where.html est un chemin virtuel, le nom sous lequel le serveur accepte de renvoyer un fichier, qui n'a pas spécialement de raison de s'appeler comme ça sur la machine en question (mais ça simplifie les choses si ce n'est pas très différent) : l'administrateur du serveur va décider comment configurer le serveur, c'est-à-dire quel fichier il doit renvoyer quand on lui demande tel ou tel chemin.

Le plus simple comme configuration est simplement d'ajouter quelque chose au début : par exemple, peut-être que quand on lui demande le chemin /some/where.html le serveur va chercher le fichier local /data/www/some/where.html c'est-à-dire à l'intérieur du répertoire /data/www (ceci n'est qu'un exemple) où on aura préalablement placé tous les fichiers que ce serveur doit accepter de renvoyer à qui le lui demande. Mais la configuration peut être arbitrairement complexe : on peut demander au serveur : si on te demande le chemin toto tu renverras le fichier titi (parce que je n'ai pas envie que tout le monde sache que je l'ai appelé titi en interne) ; si on te demande le chemin interdit tu renverras le code d'erreur 401 Unauthorized ; si on te demande le chemin machin tu renverras le code 301 Moved Permanently qui demande au navigateur client de modifier l'adresse qu'il consulte et de refaire une requête vers cette nouvelle URL ; et plein d'autres possibilités.

Globalement, tout ce qui est après le nom du serveur dans une URL de type HTTP est sous son contrôle : ce sont juste des noms virtuels sous lesquels le serveur accepte (ou pas) de renvoyer telle ou telle ressource, ça n'a pas forcément de rapport avec le nom de fichier local, même si on fait semblant que si (et j'imagine que dans le Web à papa c'était largement vrai, parce que la configuration des serveurs n'était pas aussi sophistiquée que de nos jours).

À titre d'exemple, l'adresse de mon blog est http://www.madore.org/~david/weblog/ : sur mon serveur, la configuration fait que les chemins en /~david/ sont redirigés vers /home/david/public_html/ c'est-à-dire le sous-répertoire dans mon répertoire personnel où je mets les fichiers HTML publics. Le chemin /~david/weblog/ fait donc référence au sous-répertoire /home/david/public_html/weblog/ sur mon serveur, et la configuration du serveur précise aussi que, dans ce sous-répertoire, il faut servir par défaut le fichier weblog.html et c'est donc /home/david/public_html/weblog/weblog.html (fichier prégénéré pour contenir les 20 derniers billets) qui est renvoyé. En revanche, si on demande un billet bien précis, du genre http://www.madore.org/~david/weblog/d.2023-07-25.2755.world-wide-web.html alors en fait cette adresse est un petit mensonge, il n'y nulle part de fichier nommé d.2023-07-25.2755.world-wide-web.html sur mon serveur, la configuration du serveur précise que cette page est déléguée à un « Servlet » qui va générer le contenu au vol (à partir du contenu d'une base de données de mes billets de blog) : mais cela ne change rien du tout pour l'utilisateur (à part que c'est un peu plus lent et que ça casse un peu plus souvent).

Le Web dynamique « côté serveur »

Le Web dynamique « côté serveur » fait référence au fait que la page renvoyée par le serveur peut être le résultat d'un programme quelconque. J'évoque ici ce que cela permet de faire.

On parle de page Web « statique » quand la même page renverra toujours le même contenu, à savoir juste un fichier contenu sur le serveur (et qui a souvent, quoique pas obligatoirement, un nom très en rapport avec le chemin d'accès contenu dans l'adresse, cf. ci-dessus).

Mais on peut s'écarter de ce modèle : le serveur n'est pas obligé de renvoyer le contenu d'un fichier préexistant, il peut renvoyer un fichier généré sur le champ, c'est-à-dire le résultat de n'importe quel calcul ou la sortie de n'importe quel programme que l'administrateur du serveur aura voulu prévoir. On parle de façon imprécise de page dynamique ou de Web dynamique pour ce système où, au lieu qu'une adresse renvoie un contenu et toujours le même (fichier statique), il puisse correspondre à n'importe quel contenu (sortie d'un programme, résultat d'un calcul, consultation d'une base de données, etc.) qui peut changer selon le client qui consulte, selon le moment ou la phase de la Lune, ou selon des paramètres passés à la page (cf. ci-dessous). Énormément de pages Web sont au moins en partie dynamiques de nos jours, mais précisons que je parle ici de dynamisme « côté serveur » (le serveur renvoie un contenu variable), par opposition au dynamisme « côté client » dont je parlerai plus loin, et qui est encore plus important maintenant.

Un exemple très simple de dynamisme (« côté serveur », donc) qui était très populaire dans les années 1990 était d'afficher un compteur de nombre de visiteurs sur une page Web, qui augmentait de 1 à chaque consultation. Ça n'a aucun intérêt et presque plus personne ne fait ça, mais c'est un bon exemple de contenu dynamique (et, pour trivial que soit l'usage, il représente une déviation du Web « statique » où la même page a toujours le même contenu) : la page Web incluait, en fait, une image montrant un numéro (typiquement représenté sur un affichage en faux segments LED parce que, bon, c'était les années 1990), et à chaque fois que cette image était chargée, le numéro était incrémenté. Côté serveur, c'est juste un petit programme qui renvoie une image (i.e., qui produit un fichier image), et qui, à chaque fois qu'on l'appelle, est différente.

Traditionnellement, ces programmes utilisaient un mécanisme assez simple appelé CGI (ou scripts CGI) : typiquement, on disait au serveur si un client te demande le chemin /cgi-bin/bidule alors tu vas non pas renvoyer le contenu de ce fichier mais plutôt exécuter le programme bidule et tu vas renvoyer au client ce que cette exécution produit comme données ; et même s'il y a de nos jours des tas d'autres mécanismes pour faire du dynamisme (et qu'on peut configurer le serveur comme on veut), il reste encore fréquent, même de nos jours, que les pages « dynamiques » d'un site soient situées dans un répertoire /cgi-bin (c'est plus simple dans la configuration du serveur que tout soit au même endroit).

Sur ce site-ci, par exemple, j'ai quelques vieux CGI qui traînent, comme celui-ci (référencé depuis ce billet de blog) qui crée une image psychédélique différente à chaque fois qu'on l'exécute, ou bien ce programme (référencé depuis cette page et cette entrée de ce blog) qui affiche le calendrier de l'année dans le calendrier grégorien usuel et « lunaire » (enfin, luni-solaire) que j'ai reconstruit à partir des règles de calcul de Pâques. La page renvoyée par ce dernier script ne change qu'une fois par an, pour refléter l'année en cours, mais on peut lui passer un paramètre pour demander une année précise. Disons un mot à ce sujet.

Les paramètres de requête

Les paramètres de requête sont la partie finale d'une adresse Web (précédées d'un ‘?’) : j'explique ici à quoi ils servent, en rapport avec le dynamisme « côté serveur ».

Les pages dynamiques ne sont pas très intéressantes si tout ce qui peut induire un changement est l'heure à laquelle on les consulte. Il est bien plus intéressant que le dynamisme reflète une donnée que le client a fournie, par exemple sous forme de texte entré dans un formulaire.

Pour reprendre l'exemple de ma page de calendrier, on veut pouvoir consulter non seulement le calendrier de l'année en cours, mais le calendrier de n'importe quelle année. On peut concevoir ça comme une page statique par an (et le serveur pourrait présenter cette illusion), mais si le calendrier est censé être affichable sur au moins 5 700 000 années (disons au pif), on n'a pas envie de créer d'avance 5 700 000 pages web avec autant de calendriers distincts : le calendrier doit être généré au vol (par exemple par un script CGI, cf. ci-dessus) en fonction de l'année qu'on lui demande. Comment « demander » une année ? C'est là qu'intervient une autre composante d'une adresse Web : la partie requête et les paramètres qu'elle contient.

Bon, je suis un peu embêté pour le français, par que la terminologie Web anglophone contient deux mots, request et query. Le terme request désigne l'intégralité de ce que le client envoie au serveur en HTTP, tandis que query (query string, query parameters) fait référence à cette partie finale de l'adresse, constituée de différents paramètres, dont je parle ici. Il est logique et standard de traduire l'anglais request par requête (HTTP). Je suppose qu'on devrait, du coup, traduire query par interrogation, mais ça ne semble pas standard : l'article de la Wikipédia en français correspondant à query string en anglais est chaîne de requête (et pas chaîne d'interrogation). Donc je vais dire paramètres de requête pour query parameters et éviter de parler de query tout court. Ce n'est pas une confusion très grave, mais c'est un peu agaçant quand même.

La partie paramètres de requête d'une adresse Web (ou chaîne de requête, en anglais query, cf. le paragraphe en petits caractères qui précède) est séparée par un caractère ‘?’ : elle est elle-même constituée de paramètres qui ont la forme nom=valeur et sont séparés par des ‘&’ (ou occasionnellement ‘;’). Pour prendre deux exemples très simples, mon calendrier pour 1976 a l'adresse http://www.madore.org/cgi-bin/gregorian.py?year=1976 : là-dedans, après le nom d'hôte www.madore.org et le chemin /cgi-bin/gregorian.py vient une chaîne de requête formée du seul paramètre year=1976 ; et dans une recherche Google Images du mot chat, l'adresse est https://www.google.com/search?q=chat&hl=fr&tbm=isch : là-dedans, après le nom d'hôte www.google.com et le chemin /search vient une chaîne de requête formée de trois paramètres, q=chat (qui indique le terme recherché), hl=fr (qui indique la langue de la recherche, ici le français) et tbm=isch (qui indique le type de recherche, en l'occurrence une recherche images).

La partie « chaîne de requête » d'une adresse est donc une façon de passer des paramètres, c'est-à-dire typiquement des éléments de question ou autres données variables, à une page Web, de manière à décliner la réponse en autant de possibilités.

Conceptuellement, il n'y a pas vraiment de différence entre la partie chaîne de requête et le chemin : si on navigue à l'adresse http://www.example.tld/cgi-bin/script?foo=42&bar=1729, le navigateur va demander au serveur le contenu de /cgi-bin/script?foo=42&bar=1729, ce n'est pas vraiment son problème que le début soit un « chemin » et la fin une « chaîne de requête », et le serveur répond comme il veut de toute façon, il a le droit de découper l'adresse comme il lui plaît, les serveurs Web de nos jours sont infiniment configurables de toute manière, il pourrait très bien organiser l'adresse autrement. Donc c'est plus une convention standard, par ailleurs utile, qu'un impératif.

Une raison pour laquelle elle est utile, par exemple, est qu'une page Web standard (HTML basique) peut contenir des formulaires : quand l'utilisateur rentre des valeurs dans le formulaire, le navigateur va construire une chaîne de requête qui traduit des valeurs, et c'est la façon standard (et la plus simple) de les passer au client. Par exemple, si une page HTML contient un formulaire d'entrée texte auquel on donne le nom question, et que l'utilisateur tape qui est toto? dedans, le navigateur va ajouter le paramètre question=qui+est+toto%3f dans la requête (les espaces sont convertis en ‘+’ parce qu'on ne peut pas avoir d'espace dans une URL, et toutes sortes de caractères spéciaux sont échappés en ‘%’ suivi du code hexadécimal du caractère, ou des différents octets constituants le caractère, p.ex., ‘é’ deviendrait %c3%a9).

Il est utile d'avoir une idée, sur les sites qu'on utilise fréquemment, de la signification des différents paramètres possibles. Par exemple, pour la recherche Google, voici une documentation de la signification de divers paramètres possibles (même si c'est une documentation d'une API pour programmeurs, elle s'applique largement à la recherche de base) : pour ma part, j'utilise énormément le paramètre hl=, par exemple mettre hl=en pour faire une recherche en anglais ou hl=fr pour faire une recherche en français (j'ai des raccourcis pour le faire très efficacement).

Notez qu'en général (sauf configuration contraire), quand une adresse Web contient des paramètres inattendus, soit parce qu'aucun paramètre n'était attendu, soit parce que ces valeurs précises ne sont pas attendues par le programme à l'autre bout, ces valeurs sont simplement ignorées. Par exemple, si j'ajoute test=coucou dans une recherche Google (revoici ma recherche de chat dans Google, cette fois comme https://www.google.com/search?q=chat&hl=fr&tbm=isch&test=coucou), cela n'a simplement aucun effet (mais peut-être qu'ultérieurement Google décidera de donner un sens à ce paramètre, et alors il aura un effet). Ceci conduit à une astuce qui peut servir, par exemple, pour forcer un navigateur à recharger une page si on n'est pas sûr que le bouton rafraîchir ait suffi : ajouter ?1 à la fin (ou ?blarf=1, ou bien sûr &blarf=1 s'il y a déjà des paramètres) : de cette manière, le navigateur ne peut pas savoir que c'est la même page (il ne sait pas ce qui a de l'importance pour le serveur ou pas, donc il est obligé de considérer que c'est une page complètement différente), mais le contenu renvoyé par le serveur sera, normalement, le même.

Une extension de cette astuce est utilisée par des sites Web eux-mêmes : ils ajoutent souvent des paramètres de requête qui n'ont aucun effet sur le contenu de la page elle-même mais qui servent à créer autant de déclinaisons de l'adresse pour savoir par quels canaux elle a été partagée. C'est le cas des paramètres UTM qu'on voit souvent sur des pages d'info : voyez la page Wikipédia pour plus d'explications, mais en gros quand on vous envoie un lien avec utm_medium=social ou quelque chose de ce goût-là, c'est une façon de retenir l'information que ce lien a été partagé sur les réseaux sociaux. Donc un conseil : dans une page censée être statique, ne pas hésiter à effacer tous les paramètres de requête dans l'adresse avant de la partager (disons qu'on peut au moins voir si ça marche, ça ne coûte pas grand-chose). Au hasard, j'ai vu passer récemment dans mon fil Twitter le lien https://www.lefigaro.fr/politique/roselyne-bachelot-tout-le-monde-est-d-accord-pour-une-troisieme-candidature-d-emmanuel-macron-20230626?utm_source=app&utm_medium=sms&utm_campaign=fr.playsoft.lefigarov3 : il va de soi que la bonne adresse à partager est https://www.lefigaro.fr/politique/roselyne-bachelot-tout-le-monde-est-d-accord-pour-une-troisieme-candidature-d-emmanuel-macron-20230626 et que le reste n'est là que pour aider Le Figaro à savoir qui partage ses liens et comment (apparemment ici c'est passé par une campagne par SMS), et je n'ai pas envie de les aider à ça, donc je vais virer ces bêtises. (Mais bien sûr, il faut tester si ça marche, parce que, à la base, on ne sait pas ce que signifient les paramètres de requête.)

L'identificateur de fragment

L'identificateur de fragment sert à faire un lien à l'intérieur d'une page Web. (Du moins c'est sa fonction originale, parce qu'avec l'essor du Web dynamique « côté client » il peut servir à plein d'autres choses, mais avec le point commun que le serveur n'en a pas connaissance.)

Il y a une dernière partie d'une adresse Web dont je n'ai pas parlé du tout, et qui vient tout à la fin, c'est l'identificateur de fragment. Celui-ci ne concerne pas du tout le serveur Web et n'est même pas vu par lui : il commence par le caractère ‘#’, ou croisillon, souvent mais incorrectement nommé dièse. Petite digression au sujet de ce caractère et de son nom :

Une digression sur le caractère ‘#’

Le croisillon, ou ‘#’ (U+0023 NUMBER SIGN dans Unicode), est un caractère à l'histoire compliquée, et qui se complique encore par la confusion avec plusieurs autres caractères. Son origine semble remonter à l'abréviation ‘lb’ (écrite de façon barrée, ‘℔’) du mot latin libra pour désigner la livre de poids, qui aurait été déformée et simplifiée en deux traits horizontaux croisés de deux traits verticaux (ou obliques) ; ce symbole ‘#’ est devenu standard dans certaines langues (notamment en anglais, surtout en anglais américain) pour signifier « numéro », et c'est à ce titre qu'il est apparu sur les claviers de différentes machines à écrire qu'il a été inclus dans les premiers jeux de caractères informatiques et finalement ASCII et Unicode (il a ensuite été réutilisé dans quantité se sens différents par toutes sortes de standards informatiques, par exemple pour démarrer les commentaires dans beaucoup de langages de programmation, ou par Twitter et d'autres réseaux sociaux pour marquer les hashtags). Il apparaît aussi sur les pavés de téléphones, en bas, à droite du ‘0’, et de l'autre côté de l'étoile ‘*’, et peut encore servir dans certains numéros spéciaux.

Mais en même temps, le croisillon est souvent confondu avec deux autres caractères :

Le premier est le caractère dièse, ou ‘♯’ (U+266F MUSIC SHARP SIGN dans Unicode, notation musicale qui marque l'élévation d'une note d'un demi-ton). Ce signe n'a aucun rapport à l'origine, il vient d'une déformation du bécarre ‘♮’, lui-même une sorte de lettre ‘b’ modifiée pour être « carrée » ou « dur » (par opposition au ‘♭’, qui est une lettre ‘b’ modifiée pour être « ronde » ou « molle »). Mais comme au final le croisillon ‘#’ et le dièse ‘♯’ se ressemblent énormément (la principale différence étant que dans le croisillon les traits horizontaux sont bien horizontaux et les verticaux sont un peu obliques, tandis que dans le dièse les traits verticaux sont bien verticaux et les horizontaux sont un peu obliques), énormément de gens finissent par les confondre, et comme le croisillon n'a pas vraiment de nom raisonnable, surtout en français (personne ne dit jamais croisillon sauf d'insupportables pédants), on se retrouve à dire dièse.

L'autre confusion possible est avec le symbole de la livre ‘£’ (U+00A3 POUND SIGN dans Unicode). Là c'est vraiment un coup du club contexte : le croisillon ‘#’ vient, comme je l'ai dit, d'une déformation du symbole de la livre de poids, tandis que ‘£’ est le symbole de la livre monétaire (i.e., la livre sterling, qui vient elle-même, bien sûr, de la livre de poids), donc les deux s'appellent parfois pound sign en anglais ; mais en plus de ça, le symbole ‘£’ se trouve, sur les claviers britanniques au même emplacement (shift-3) que le symbole ‘#’ sur les claviers américains, donc on a deux symboles différents appelés par le même nom et qui se trouvent au même endroit sur des claviers différents… on imagine les confusions que cela peut causer.

Bref, le symbole ‘#’ peut être nommé de toutes sortes de façons différentes : j'ai dit qu'en français il devrait s'appeler croisillon mais personne ne dit jamais ça et tout le monde l'appelle dièse. En anglais, le problème est plutôt inverse, il a trop de noms : à côté de sharp (qui résulte de la confusion avec ‘♯’ comme en français) et pound [sign] (qui résulte de ou entretient la confusion avec ‘£’), on trouve number [sign], ce qui est raisonnable, hash (dont on ne sait pas bien l'origine, mais c'est très courant, et les hashtags ont popularisé ce terme), mais aussi des choses plus originales comme octothorpe ou, de façon pas très sérieuse, shibboleth (une référence à Juges 12:6, justement parce qu'on ne sait pas comment dire ce truc).

Bref, dans une URL comme http://www.example.tld/some/where.html#blarf, la partie #blarf est un identificateur de fragment. Son intérêt, au moins à l'origine (et ça reste encore largement vrai) est de permettre de faire un lien à l'intérieur d'une page Web : le document HTML (ou éventuellement un autre type de document) va pouvoir définir des points à l'intérieur de lui-même, par exemple pour les principales parties, les notes en bas de page, ou n'importe quel autre point précis qu'on peut souhaiter marquer spécialement, et leur donner un identifiant de fragment arbitraire qui sera ensuite référencé par une telle adresse. À titre d'exemple, les différents liens dans la table des matières de ce billet (ainsi que le lien que je viens de faire vers elle) sont des liens internes qui ne diffèrent que par l'identificateur de fragment, le chemin étant toujours le même.

L'identificateur de fragment n'est pas transmis par le navigateur au serveur Web (le navigateur client demande juste /some/where.html), c'est le navigateur qui, ensuite, positionne la vue affichée sur le fragment désigné. Donc en principe (dans le Web à papa), demander http://www.example.tld/some/where.html#blarf ou http://www.example.tld/some/where.html montrera de toute façon la même page, simplement positionnée différemment. Si on navigue vers un lien pointant vers la page actuelle avec seulement l'identificateur de fragment qui change, le navigateur n'effectue aucune requête HTTP (il ne contacte pas du tout le serveur), il se contente de repositionner la vue dans la page courante.

(Et on en déduit aussi que cette section est mal positionnée dans cette entrée, parce que je suis censé parler ici du travail du serveur Web et que justement le fragment ne le concerne pas, mais ça me semblait logique de l'évoquer quand même ici en tant que composante d'une adresse Web.)

En pratique, avec l'essor du Web dynamique « côté client » dont je parlerai plus bas, l'identificateur de fragment s'est mis à pouvoir servir à toutes sortes d'autres choses, notamment des paramètres « côté client », mais j'en parlerai plus loin.

Le travail du navigateur Web

Dans cette partie, je me penche sur le travail du client (navigateur) Web, et la manière dont il convertit le contenu que le serveur lui a renvoyé en quelque chose d'affiché à l'écran.

À ce stade-là de mes explications, j'ai couvert la manière dont le navigateur côté client contacte le serveur de l'adresse demandé, lui parle (en HTTP) et obtient la page à afficher. Reste à expliquer ce qu'il en fait. Si la page est une image ou un fichier texte brut, par exemple, je n'ai pas grand-chose à dire. Mais le plus souvent, au moins pour une adresse qu'on a des chances de consulter directement, c'est du HTML.

Le HTML et sa syntaxe de base

Le HTML est le langage dans lequel les pages hypertexte sont écrites. C'est un format texte assez simple, structuré au moyen de balises : je décris ici sa syntaxe de base à travers quelques exemples.

Le HTML est, avec le HTTP, l'un des deux piliers du Web original. C'est un langage, ou format de fichier, qui décrit une page hypertexte sous forme d'un mélange de texte directement lisible et de balises qui servent à marquer du contenu qui doit être, par exemple, mis en relief, présenté sous forme de tableau, utilisé comme titre de page, présenté comme un lien, ou toutes sortes d'autres choses de ce genre. Voici un exemple de bout de HTML, simple mais néanmoins illustratif :

<p><a href="http://fr.wikipedia.org/">Wikipédia</a>, qu'on trouvera à l'<abbr title="Uniform Resource Locator">URL</abbr> <code>http://fr.wikipedia.org/</code>, est une encyclopédie <strong>ouverte</strong>.<br />Les pages de cette encyclopédie sont affichées en <abbr title="HyperText Markup Language">HTML</abbr> même si ce <em>n'est pas</em> leur format original.</p>

et voici le résultat :

Wikipédia, qu'on trouvera à l'URL http://fr.wikipedia.org/, est une encyclopédie ouverte.
Les pages de cette encyclopédie sont affichées en HTML même si ce n'est pas leur format original.

Le texte est directement lisible, comme on le voit, mais il est entremêlé de balises : la paire de balises <p></p> qui entoure l'ensemble indique que tout ceci est un paragraphe de texte (le sauts de ligne sont — en général — ignorés dans le HTML, c'est le découpage indiqué par les balises <p> qui sert à la présentation en paragraphes du texte) : ici, <p> est la balise ouvrante et </p> la balise fermante (dans ce cas précis, elle pourrait être omise dans la plupart des versions du HTML). L'ensemble contenu entre la balise ouvrante et la balise fermante s'appelle un élément (mais il faut admettre que les termes balise et élément sont parfois utilisés de façon un peu interchangeable).

De même, la paire de balises <em></em> qui entoure les mots n'est pas sert à mettre en relief (= marquer l'emphase), ce qui va être représentée graphiquement comme des italiques (mais le sens est bien l'emphase, pas les italiques, car le HTML cherche à séparer le fond et la forme ; il y a cependant une autre balise qu'on est censé utiliser pour les italiques lorsque leur sens est différent de l'emphase) ; et la paire de balise <strong></strong> qui entoure le mot ouverte sert à marquer une emphase forte, qui va être représentée graphiquement comme du gras. La paire de balise <code></code>, quant à elle, sert à marquer du code informatique, qui sera représenté graphiquement par une police à espacement fixe comme il convient à une URL.

La paire de balises <abbr></abbr> marque une abréviation et son rôle est principalement de guider les lecteurs vocaux pour leur signaler qu'il faut lire les lettres une par une (achtéèmèl) plutôt qu'essayer de prononcer les quatre consonnes consécutivement. Mais ici je leur ai ajouté un attribut title, représenté par title="HyperText Markup Language" à l'intérieur de la balise ouvrante : l'attribut title peut servir sur n'importe quelle balise HTML et représente un texte explicatif qui sera affiché dans une fenêtre flottante transitoire si on passe la souris au-dessus (tooltip en anglais ; Wikipédia m'apprend que ceci s'appelle une infobulle en français, mais honnêtement je n'ai jamais entendu ce mot) ; cet attribut est essentiellement utilisé sur une abréviation pour en préciser le sens à la première utilisation (certains navigateurs vont, d'eux-mêmes, ajouter un souligné pointillé pour signaler que cette bulle explicative est disponible), sur un lien pour donner une indication de là où il conduira, et sur une image pour décrire son contenu (mais c'est différent de l'attribut alt qui sert à remplacer l'image quand elle ne peut pas être affichée ou à destination des non-voyants). Bon, malheureusement, cet attribut title est simplement ignoré sur les navigateurs à interface tactile, et c'est la merde, et ceci est un bon exemple des nombreux problèmes qui polluent le HTML.

Enfin, la paire de balises <a></a> (le ‘a’ est l'initiale du mot anchor) demande la création d'un hyperlien, et la destination de l'hyperlien est indiquée par l'attribut href de la balise (ouvrante, les attributs sont toujours portés par la balise ouvrante), qui contient l'URL de la cible du lien : cette balise a est sans doute la balise la plus importante du HTML parce que c'est elle qui donne vraiment son sens à l'hypertexte.

Enfin, la balise <br /> qui n'est ni ouvrante ni fermante mais isolée, est utilisée pour forcer un passage à la ligne à l'intérieur d'un paragraphe (cela ne démarre pas un nouveau paragraphe et l'espacement sera comme à l'intérieur d'un paragraphe ; c'est plutôt déconseillé, mais je m'en sers comme exemple de balise isolée). En fait, on pourrait l'écrire <br> dans la plupart des versions du HTML.

Je ne rentre pas plus dans les détails de la syntaxe du HTML : il y a plein d'autres choses qu'on pourrait dire, mais ce n'est pas mon propos ici d'expliquer comment écrire du HTML : j'évoque sa syntaxe uniquement parce qu'elle me semble pertinente pour avoir une vue d'ensemble du Web, y compris parce qu'elle déteint parfois sur les codes d'écriture (par exemple vous verrez parfois des gens écrire c'était <sarcasme>super bien</sarcasme> en imitant des balises HTML même si ce n'en sont pas et même si leur texte n'est pas du HTML, ou en tout cas pas à ce niveau d'affichage, c'est-à-dire en reprenant le style des balises HTML mais comme un code d'écriture à destination des humains).

Il va de soi que si on veut écrire un ‘<’ dans un fichier HTML, il faut l'échapper pour qu'il ne soit pas confondu avec le début d'une balise : il faut l'écrire sous la forme &lt; (et, pour la même raison, ‘>’ et ‘&’ doivent être écrits sous la forme &gt; et &amp; respectivement). À cause de cette convention d'échappement, on voit parfois des textes contenant par erreur des choses comme &lt; même si ce ne sont pas ou plus du HTML : cela fait partie des très nombreux problèmes de niveau d'échappement qui pullulent en informatique.

Aparté : écrire le HTML à la main ?

Je souligne que la syntaxe du HTML était, à l'origine, prévu pour être écrite à la main, et ce n'est pas particulièrement compliqué. D'ailleurs, le HTML de ce blog est écrit à la main (j'ai juste des raccourcis commodes dans mon éditeur pour m'aider à entrer les balises les plus courantes, mais ce que je veux dire est que le texte que je vois dans mon éditeur est bien le HTML que je vais afficher — enfin, j'ai un moteur de blog derrière qui va le transformer un peu, mais peu importe, il est substantiellement tel qu'il sera renvoyé par le serveur ; ça ne m'empêche pas d'aller de temps en temps voir dans un navigateur quel est le rendu de ce que j'ai tapé).

Mais de nos jours, la majorité (l'immense majorité ? je ne sais pas) du HTML qu'on trouve en ligne n'est pas écrit à la main. Soit il résulte d'une transformation à partir d'un autre format (c'est le cas pour Wikipédia, justement), soit il est produit automatiquement par un programme, soit il est écrit par un humain au sein d'un éditeur graphique qui va montrer seulement le résultat, pas le HTML sous-jacent, en fournissant des méthodes à la souris pour créer un lien, mettre en relief, etc. Le problème de ces outils graphiques est que cela conduit à ce que l'auteur du texte se concentre sur l'apparence qu'il voit dans l'outil qu'il est en train d'utiliser, et néglige, par exemple, les balises qui ne se voient pas mais qui peuvent avoir un effet ailleurs (aider les non-voyants, guider les moteurs de recherche, simplifier le traitement automatisé, etc.).

Ceci m'amène à une autre digression :

Aparté 2 : ce qui se voit et ce qui ne se voit pas

Les technologies du Web, et le HTML spécifiquement, sont en perpétuelle tension au sujet de la séparation entre le fond et la forme, entre la sémantique et le rendu graphique. Par exemple, emphase est une sémantique, tandis que italiques est un rendu graphique.

Le cycle qui s'est répété d'innombrables fois dans l'histoire du Web (et du reste de l'informatique) est le suivant : on met en place une technologie censée tenir compte d'une information sémantique utile, les gens se comportent comme des paresseux et ne renseignent pas cette information ou n'utilisent la technologie en question que pour les effets qu'ils voient directement sur l'écran, et au bout d'un moment il devient trop coûteux de continuer à maintenir cette technologie donc elle tombe à l'abandon ou est officiellement retirée des standards.

La raison pour laquelle il est important sur le Web de chercher plus loin que ce qui s'affiche directement sur l'écran est que tout le monde ne consulte pas le Web avec un navigateur graphique ou, même s'ils le font, il n'est pas forcément le même pour tous. Il y a des gens qui ont toutes sortes de problèmes d'accessibilité, les plus évidents étant les non-voyants qui utilisent un synthétiseur vocal, mais on peut aussi penser aux malvoyants qui ont besoin d'afficher le texte très gros. Mais il y a toutes sortes d'autres raisons de vouloir séparer le fond et la forme : les moteurs de recherche et, maintenant ou bientôt, la constitution de texte pour une IA, pourraient bénéficier de toutes sortes d'informations ancillaires dans une page HTML qui ne sont pas directement affichées dans un navigateur graphique, ou en tout cas pas dans la vue par défaut.

L'exemple le plus évident de telles informations sémantiques ancillaires non immédiatement visibles est la langue dans laquelle un passage est écrit. Quand je tape du HTML, j'indique toujours scrupuleusement, au moyen des attributs lang (et aussi xml:lang) la langue du contenu (par exemple si je cite une expression anglaise dans un texte français, je la marque comme telle dans le HTML) : cela reste complètement invisible au niveau du rendu ; c'est censé aider les synthétiseurs vocaux à choisir la bonne langue à utiliser pour la prononciation (il ne vous aura pas échappé que le mot français mine et le mot anglais mine s'écrivent exactement pareil, mais ils ne se prononcent pas pareil), mais aussi les moteurs de recherche à correctement catégoriser le contenu, aux traducteurs automatiques à savoir quelle langue source utiliser, et ainsi de suite. En vérité, c'est vraiment tragique, même le correcteur orthographique de Firefox n'est pas foutu de tenir compte de l'indication de langue pour sélectionner le dictionnaire contre lequel corriger chaque passage : j'ai l'impression de pisser dans un violon ! Quant aux moteurs de recherche et aux traducteurs automatiques, ils utilisent stupidement une détection automatique d'après le texte qu'ils voient, et ignorent purement et simplement les attributs lang contenus dans le document. C'est à la fois stupide, rageant, et frustrant : les cours de HTML ne vous expliquent quasiment jamais que si vous citez une langue différente de celle de votre document principal vous devez renseigner l'attribut lang, les gens ne le font pas parce qu'ils ne voient aucun effet, du coup les attributs lang sont généralement faux ou non renseignés ou, au mieux, renseignés automatiquement. Du coup ces attributs ne servent à rien, du coup personne n'en tient compte.

Un autre exemple assez typique est celui des balises <abbr></abbr> et <acronym></acronym> : la première était censé servir à marquer les abréviations qui se prononcent lettre par lettre (HTML se prononce achtéèmèl, enfin, /aʃteɛmɛl/) et la seconde celles qui se prononcent comme si c'était un mot (ICANN se prononce comme I can en anglais ; en français vous pouvez franciser ou pas, mais en tout cas on ne dira pas icéaènèn). J'ai toujours été très soigneux, dans mon HTML, de bien marquer toutes les abréviations par l'une ou l'autre de ces balises (quitte à m'emmerder à écrire CD-ROM comme <abbr>CD</abbr>-<acronym>ROM</acronym> parce que la première partie se prononce lettre par lettre mais la seconde se prononce comme un mot ; et à m'arracher les cheveux pour savoir comment écrire sortes sortes de cas douteux). Je pensais naïvement aider, par exemple, les synthétiseurs vocaux à correctement rendre la prononciation. Mais en fait, il s'avère que « personne » n'utilisait correctement cette distinction entre les deux balises, et la balise <acronym></acronym> a purement et simplement été supprimée du HTML. Ce qui veut dire que moi qui m'emmerdais à la renseigner à bon escient, j'ai dû écrire du code pour la remplacer par <abbr class="acronym">ICANN</abbr> de manière à préserver cette information, et que de toute façon j'ai la sensation d'avoir été floué parce qu'il est apparemment impossible de donner aux synthétiseurs vocaux une indication de prononcer lettre par lettre ou au contraire comme si c'était un mot (ils se basent uniquement sur des dictionnaires internes) : toutes les technologies qui avaient été proposées pour ça (comme les feuilles de style orales) ont été abandonnées parce que les gens ne s'intéressent qu'à ce qui se voit. Je me sens assez trahi par toute cette histoire.

(J'évoque l'accessibilité pour les non-voyants, mais ce n'est même pas vraiment ça mon problème : il se trouve qu'une bonne présentation sémantique aidera certainement l'accessibilité, mais ma préoccupation va bien au-delà de l'accessibilité : je considère que le texte que je tape a un sens bien précis, et c'est cette sémantique qui m'intéresse plus que ce qui va être rendu sur l'écran ou prononcé par un synthétiseur vocal ou quoi que ce soit, donc je suis juste choqué quand la sémantique passe à la trappe à la faveur de la forme.)

Le chaos des versions du HTML

Le HTML a évolué de façon chaotique à cause de l'écart entre le standard officiel et la manière dont les navigateurs (qui se faisaient la guerre dans les années 1990–2000) interprétaient le format. J'évoque ici la manière dont ce chaos s'est développé, puis a été largement résorbé par l'introduction du HTML5.

Le HTML avant le HTML5

Le HTML a une histoire… compliquée. Il existait des formats de « texte à balises » bien avant HTML (cela remonte à la fin des années 1960, je crois ; ils servaient par exemple à saisir des formats spécialisés, comme des dictionnaires, des notices bibliographiques, des catalogues), et notamment un méta-format appelé SGML (normalisé par l'ISO) destiné à standardiser et uniformiser des syntaxes à balises de façon générale. Fort logiquement, Tim Berners-Lee a choisi de définir HTML comme une instance de SGML, et c'est ça qui a servi de base à sa normalisation.

Malheureusement, ce qui a surtout caractérisé la décennie 1990, c'est un divorce croissant entre le HTML normalisé (basé sur SGML) et le HTML pratiqué par les navigateurs Web. Le problème est que le standard SGML est extrêmement complexe et difficile à mettre en œuvre informatiquement, donc à part les validateurs HTML (c'est-à-dire les applications destinées spécifiquement à vérifier que du HTML est correctement conforme à la norme), personne n'interprétait le HTML en se basant sur la norme SGML. Et de fait, les humains qui tapaient du HTML (car dans les années 1990 le HTML était surtout tapé à la main) souvent ne respectaient pas la norme, et les navigateurs interprétaient un peu comme ils pouvaient (et parfois différemment de l'un à l'autre) ce HTML écrit à la main.

On a donné un nom à cette façon d'écrire ou d'interpréter le HTML : la soupe de balises. Un exemple de soupe de balises pourrait être quelque chose comme ceci : <i>c'est <b>très</i> important</b> (sachant que la balise i représente des italiques et la balise b du gras) : ceci n'est pas du HTML valable car les balises ne sont pas correctement imbriquées, elles se chevauchent (la balise i est fermée alors que la balise b ne l'est pas encore) ; les navigateurs pourraient comprendre ça en mettant très en gras italiques (ce qui est certainement l'intention voulue) et peut-être aussi, ou pas, en mettant important en gras non italiques (ce qui est peut-être l'intention voulue, ou peut-être pas, qui sait).

Vers la fin des années 1990, on était arrivé à la combinaison des problèmes suivants :

  • les validateurs HTML, et seulement eux, lisaient le HTML conformément à sa norme, comme du SGML,
  • les navigateurs Web lisaient le HTML comme une « soupe de balises », pas toujours de façon cohérente d'un navigateur à l'autre, et d'ailleurs ils inventaient parfois leurs propres balises spécifiques et avaient des idiosyncrasies de rendu,
  • les humains écrivaient du HTML directement, vérifiaient parfois son affichage dans un navigateur, rarement deux, et allaient très rarement consulter un validateur, et le HTML était souvent invalide selon la norme (ou, parfois pire encore, valide mais pas avec l'interprétation que l'humain qui l'avait écrit souhaitait),
  • bref, le divorce était croissant entre le HTML normalisé et le HTML réellement pratiqué en ligne.

Je ne rentre pas dans l'histoire des versions du HTML parce que cela concerne essentiellement le HTML normalisé essayant de courir après le HTML réellement pratiqué par les navigateurs, se disputant sur ce qu'il fallait normaliser, proposant des choses trop compliquées, se faisant de nouveau doubler par les navigateurs, etc. La version qui a fini par atteindre une certaine stabilité était la version 4.0 (ou 4.01) vers 1997–2000.

À peu près au même moment (la fin des années 1990) est apparu un nouveau standard : XML. Celui-ci était destiné à simplifier considérablement SGML pour rendre son traitement informatique gérable dans des petites applications sans avoir à inclure l'incroyable complexité de ce que la norme SGML prévoyait. Le XML a été un succès énorme et est un des grands formats d'échange de données informatiques (ou plus exactement, un méta-format, parce que le XML lui-même ne dit pas grand-chose : juste la manière dont on ouvre et ferme les balises, pas ce que ces balises signifient) ; mais le XML est plutôt destiné à l'échange et au stockage de données automatisées (produites par un programme, à destination d'un autre) : pour les humains, il est assez malcommode, parce qu'il est très pointilleux : la moindre erreur de syntaxe rend le document mal-formé, et il est alors obligatoire de le refuser (le but de cette règle étant d'éviter de retomber dans le chaos des versions du HTML causé par des navigateurs trop permissifs).

Des instances de HTML basées sur XML (à la place du SGML) ont été développées (sous le nom de XHTML), mais elles n'ont pas eu un énorme succès parce que, comme je le dis plus haut, le XML est très pointilleux et pas très commode à écrire à la main (ou alors il faut systématiquement valider au moins la partie XML). C'est cependant avec le XHTML que la convention s'est imposée d'écrire les balises du HTML en minuscules (le XHTML l'impose alors que les versions précédentes du HTML sont indifférentes à la casse).

Tout a changé avec l'avènement du HTML5.

Le HTML5

Le standard HTML5, finalisé entre 2008 et 2014, représente à sa sortie la première évolution majeure du HTML depuis en gros une décennie : il cherche à résoudre les problèmes assez contradictoires de réunifier les technologies du Web autour d'un standard commun, de mettre fin au chaos des versions incompatibles du HTML, de définir proprement la syntaxe du langage sans embarquer avec lui la complexité du SGML, et en même temps de moderniser le tout pour permettre une prise en compte de technologies qui n'existaient pas une décennie avant (à commencer par les smartphones).

La réussite n'a pas été parfaite, mais elle a été bien meilleure qu'on ne pourrait l'imaginer à la lecture d'un programme si ambitieux.

Pour résoudre le chaos des incompatibilités de syntaxe, le HTML5 abandonne complètement le très complexe SGML, et définit une syntaxe ad hoc, décrite de façon extrêmement précise, inspirée de la soupe de tags que les navigateurs lisaient de toute façon, et destinée à être compatible avec elle. Cette syntaxe est certes compliquée, mais comme elle est compatible avec ce qui se faisait en pratique sur les versions antérieures du HTML, et qu'elle est assez précisément définie pour éviter les divergences entre navigateurs (et impose certaines erreurs en cas de faute de syntaxe), elle semble avoir réussi à éviter le chaos de la prolifération d'interprétations incompatibles. Une seule autre syntaxe est permise, c'est celle basée sur XML (et plutôt destinée à des documents HTML produits automatiquement) ; les deux syntaxes permises (XML et ad hoc) sont suffisamment compatibles pour qu'on puisse produire des documents « polyglottes » qui peuvent être lus soit selon la syntaxe ad hoc du HTML5 soit selon la syntaxe XML (c'est possible mais ce n'est pas entièrement trivial), et c'est censé être le cas de ce blog ainsi que de nombreuses autres pages de mon site Web.

Pour moderniser le Web, le HTML5 unifie avec le HTML des standards qui étaient restés séparés : le format d'images vectorielles SVG (qu'on peut donc utiliser au sein d'une page Web sans avoir à faire des fichiers séparés pour les images) ainsi que le format MathML d'affichage des formules mathématiques (que Chrome vient seulement récemment récemment de se décider à intégrer complètement), mais aussi ARIA pour l'accessibilité (p.ex. aux personnes handicapées). Cette unification a permis d'améliorer la disponibilité de ces technologies et leur standardisation en les agrégeant autour d'une définition commune de ce qui constitue le Web.

Mais les améliorations du HTML5 se font aussi en lien avec JavaScript, dont il faut que je parle ailleurs.

Le style : CSS

Les feuilles de style (CSS) permettent de définir l'apparence d'une page Web de manière en principe séparée de son fond, qui est décrit par le HTML.

Les premières versions du HTML ne prévoyaient pas de mécanisme pour, par exemple, changer de couleur de texte ou de police de caractères : l'idée était que ce n'est pas à l'auteur d'une page Web de spécifier ce genre de choses (ce ne sont pas des informations sémantiques ; d'ailleurs, à l'époque, il y avait encore beaucoup d'écrans monochromes, donc utiliser la couleur était de toute façon une mauvaise idée).

Mais au milieu des années 1990, les navigateurs Web tels que Netscape ont inventé toutes sortes de balises spécifiques pour permettre de préciser toutes sortes d'aspects de l'affichage : par exemple, une balise <font> pour préciser la police de caractères et sa couleur, un attribut bgcolor pour préciser la couleur de fond, ce genre de choses (et ne parlons pas de les redoutables balises <blink> pour le clignotant et <marquee> pour du texte qui défile). Le Web des années 1990 était clignotant et plein de couleurs très kitch.

Ceci allait à l'encontre du principe de séparation du fond et de la forme que le HTML voulait maintenir. Pour répondre à la demande de personnalisation de la forme tout en préservant ce principe, un nouveau standard a été développé pour complémenter HTML : le CSS (les feuilles de style). L'idée est (ou plutôt, devrait être) que HTML définit la sémantique du document : tel passage est à mettre en relief, tel passage est une citation, etc. ; tandis que CSS (qui peut être maintenu dans un fichier à part, ou intégré à divers niveaux du HTML) définit l'apparence à donner. Ce standard, démarré dès les années 1990, a mis assez longtemps à s'imposer vraiment : ou plus exactement, il a mis assez longtemps à devenir vraiment standard (chaque navigateur implémentait CSS avec ses idiosyncrasies bizarres, et pendant longtemps il était terriblement difficile de reproduire la même apparence sur Netscape et Internet Explorer). Maintenant, CSS est raisonnablement unifié et est la façon parfaitement normale de définir l'apparence d'une page Web.

Néanmoins, si le standard a assez bien réussi à s'imposer, on peut dire que c'est un échec au sens où le but initial a été perdu en cours de route : la séparation du fond et de la forme n'est absolument pas respectée. Dans un monde bien fait, ce n'est pas l'auteur d'une page Web qui devrait décider comment elle s'affiche, c'est au lecteur de choisir ses polices et couleurs préférées ; a minima, n'importe quel site devrait proposer un large choix de styles d'affichage au-dessus de bases standard. Dans la pratique, chaque page Web impose ses goûts jusque dans les plus petits détails, et l'utilisateur n'a guère comme choix que de zoomer plus ou moins, et parfois entre un thème « clair » et un thème « sombre » (cela tend à devenir standard). Ce site-ci ne fait pas exception : ce n'est pas vraiment ma faute, les standards ne permettent tout simplement pas de mettre le pouvoir entre les mains de l'utilisateur où il devrait se trouver, on peut régler toutes sortes de détails insignifiants sur l'affichage du texte et les couleurs, mais pas demander à l'utilisateur quelles sont ses préférences (ou alors ça se fera avec une quantité hallucinante de JavaScript que rien n'a été prévu pour standardiser, ce qui rend tout effort largement inutile).

Le Web dynamique « côté client » : JavaScript

Le JavaScript est un langage de programmation central au Web moderne, qui permet d'exécuter des programmes dans le navigateur, ouvrant la voie à des pages dynamiques « côté client » pouvant aller jusqu'à de véritables « applications Web ». J'explique ici comment ce concept est apparu, puis en quoi le dynamisme « côté client » contraste avec mais aussi complémente le dynamisme « côté serveur ».

Mais s'il y a une technologie qui a vraiment changé la face du Web, ce n'est pas tant la 5-ième version du HTML ni les feuilles de style CSS : c'est le JavaScript et le dynamisme « côté client ».

JavaScript, donc (ou ECMAScript, qu'on peut considérer comme synonyme), est un langage de programmation. Sa particularité est de permettre d'écrire des programmes qui vont s'exécuter dans le navigateur côté client. Cela permet tout ou n'importe quoi entre permettre des pages plus réactives, décharger le serveur de certaines tâches plus commodes à exécuter côté client, ou faire tourner des jeux ou autres programmes complets dans le navigateur. La quasi totalité des pages Web, de nos jours, incluent au moins une certaine dose de JavaScript (ce blog est inhabituellement minimal de ce point de vue-là, mais certains billets y font quand même appel et au moins l'affichage du nombre de commentaires ou la protection des adresses mail contre le spam fait appel à JavaScript).

Une brève histoire de JavaScript et de son évolution

Pour simplifier à l'extrême une histoire compliquée : l'idée de faire tourner des programmes dans un navigateur est apparue dès les années 1990. Le premier langage pressenti à cet effet était le langage Java (un langage prévu pour tourner à l'identique sur des ordinateurs différents) : l'idée était qu'on écrirait des applications spécifiques (dites applets Java) destinées à être embarquées au sein d'une page Web ; comme Java était prévu pour rendre le code transportable d'une architecture informatique à une autre, il était assez naturel de chercher à s'en servir dans ce sens. Mais les applets Java étaient compliquées à déployer (il fallait les compiler et les fournir comme des fichiers autonomes) et l'interface avec le reste de la page Web était minimal. Le langage JavaScript qui, malgré son nom, n'a que peu de rapport avec Java sinon une vague similarité de syntaxe, développé au sein du navigateur Netscape, se présentait comme une alternative plus légère à Java : pas besoin de compiler à l'avance, on peut se contenter d'écrire du JavaScript au milieu du HTML, et celui-ci a une meilleure interaction avec le reste de la page. De nos jours, à la fois Java et JavaScript ont profondément évolué : Java a cessé d'être disponible dans les navigateurs Web, mais il demeure un majeur dans d'autres domaines informatiques (par exemple, les apps Android sont normalement écrites en Java ; mais Java sert aussi parfois dans les serveurs Web) ; quant à JavaScript, il est partout dans les pages Web (dans le navigateur ; et parfois aussi côté serveur), mais il a énormément changé depuis les années 1990, à la fois dans le langage lui-même et dans ses capacités d'interaction avec le HTML.

Entre Java et JavaScript, il y a un autre langage du Web qui a eu son heure de gloire (ou d'infamie), c'est Flash (Macromedia Flash, ultérieurement renommé en Adobe Flash), un langage maintenant essentiellement défunt qui, surtout dans les années 2000 et 2010, servait à faire toutes sortes de pages animées qui maintenant se feraient en JavaScript, par exemple des jeux vidéos en ligne : cette technologie était détestée à cause du nombre de trous de sécurité qui imposaient sa mise à jour en gros chaque semaine (le lecteur Flash était indépendant du navigateur et se présentait comme une addition spéciale, propriétaire, de la même manière que Java mais à la différence de JavaScript qui est vraiment intégré au navigateur). Elle a aujourd'hui pour ainsi dire disparu, mais la laissé des traces en ce que de nombreux choix de conception du HTML5 et du JavaScript viennent de l'impératif de pouvoir refaire tout ce que Flash permettait.

Comme essentiellement toutes les technologies Web nées dans les années 1990 (HTML, CSS et, donc JavaScript), il y a eu une phase de développement désordonné marqué par la guerre des navigateur entre les deux géants de l'époque, Netscape et Internet Explorer (sur laquelle je devrais écrire quelque chose, mais je commence à fatiguer), chacun partant dans sa propre direction en recopiant à sa sauce les idées du principal concurrent ; puis une phase de restandardisation : JavaScript fait normalement référence au langage développé chez Netscape, JScript au langage équivalent chez Microsoft (dans Internet Explorer), et ECMAScript au langage standardisé cherchant à mettre de l'ordre dans le chaos.

Mais JavaScript n'a pas seulement évolué en ce sens d'une divergence suivie d'une restandardisation : il a aussi changé par d'autres aspects. Par exemple, la manière dont le JavaScript original modifiait la page Web dans laquelle il s'inscrivait était essentiellement syntaxique, le programme JavaScript donnant l'ordre d'écrire des morceaux de HTML à tel ou tel endroit ; le JavaScript moderne, lui, fonctionne de façon tout à fait différente, en manipulant le document comme un objet abstrait (l'arbre DOM), ce qui est bien plus propre et évite toutes les questions relatives à la syntaxe concrète du HTML.

En fait, le JavaScript d'origine était destiné à faire de simples petites bidouilles sur une page Web (par exemple, vérifier que les champs d'un formulaire sont sensés avant de l'envoyer au serveur), l'idée étant sans doute que les programmes vraiment complexes seraient écrits en autre chose (comme Java ou, plus tard, Flash). Le JavaScript moderne non seulement permet, mais est effectivement utilisé, pour des programmes d'une complexité démesurée (on trouve des programmes JavaScript qui font tourner un navigateur complet dans une page Web ou même, sans doute le plus impressionnant, l'émulateur d'un ordinateur complet) : en pratique, on a donc en JavaScript des jeux, des suites bureautiques, ou des programmes de tout genre. Essentiellement n'importe quoi peut être écrit en JavaScript : même si on ne veut pas réécrire un programme existant, il existe des compilateurs-traducteurs permettant de convertir en JavaScript un programme écrit dans un autre langage.

Mais si on peut se réjouir de ces évolutions, il y en a une autre qui les accompagnées de façon assez inévitable : la minification/obfuscation du JavaScript fourni. Car si à l'origine le JavaScript inclus dans une page Web était tel qu'écrit par des humains et donc raisonnablement lisible (avec des commentaires, une présentation structurée, des noms de fonctions et de variables du programme qui décrivent plus ou moins ce qu'elles font, etc.), de nos jours le JavaScript accompagnant n'importe quel site web est « minifié », c'est-à-dire rendu illisible par suppression des commentaires et de l'espacement et remplacement de tous les noms de variables par des noms de taille minimale. La raison ostensible de cette minification est d'économiser de la bande passante réseau (cela ne sert à rien de gâcher du réseau à transmettre les commentaires d'un code JavaScript qui est simplement destiné à être exécuté par le navigateur et pas à être lu par l'utilisateur) ; mais derrière ce prétexte, il y a aussi un enjeu de contrôle : permettre à l'utilisateur de lire le code JavaScript lui donne plus de chances d'arriver à l'analyser, le comprendre, et le modifier éventuellement. Ce qui devrait être un droit fondamental du Web (un site Web que je consulte fournit du code qui tournera sur mon navigateur mais c'est quand même moi, l'utilisateur, qui dois rester le maître en dernier recours de ce que mon navigateur fera, et j'ai le droit moral de désactiver ou modifier n'importe quel bout de ce code, pensez par exemple à la guerre entre les bloqueurs de pub et les anti-bloqueurs de pub : ce sont évidemment les utilisateurs qui ont le droit fondamental de désactiver les pubs et les anti-bloqueurs de pub, et chercher à les en empêcher est profondément immoral), mais ce droit fondamental est gravement remis en question par la minification qui transforme le JavaScript en un langage essentiellement binaire (à prendre ici au sens : lisible uniquement par un ordinateur).

Dynamisme côté client et dynamisme côté serveur

Bref, le dynamisme « côté client » consiste à intégrer dans une page Web des morceaux de JavaScript (ou même la faire construire entièrement par du JavaScript), qui s'exécute dans le navigateur, c'est-à-dire « côté client », pour effectuer les traitements ou réaliser l'interface utilisateur qu'on souhaite donner à la page Web (et qui se transforme ipso facto en une véritable application tournant dans le navigateur). Ceci s'oppose au dynamisme « côté serveur », dans lequel le client ne fait rien ou pas grand-chose, se contentant d'afficher des pages renvoyées par le serveur et modifiées à la demande pour tenir compte des données saisies par l'utilisateur ou toute autre information pertinente. Le dynamisme côté serveur peut utiliser tout langage de programmation qui plaît à l'administrateur du serveur : historiquement le PHP a énormément servi pour ça, mais Java, JavaScript, Perl, Ruby, Python, toutes sortes d'autres langages sont possibles, par contraste au dynamisme côté client qui est essentiellement cantonné à JavaScript car c'est le seul langage garanti disponible, même si on peut éventuellement utiliser un langage compilé vers JavaScript, c'est-à-dire transformé en JavaScript après écriture.

Un exemple très simple pour illustrer la différence pourrait être une page qui permette de faire un calcul mathématique, disons, zoomer sur l'ensemble de Mandelbrot :

  • Dans une version dynamique purement côté serveur, le navigateur demanderait au serveur une image dont les paramètres de requête préciseraient le centre et le niveau de zoom à calculer (quelque chose comme /mandelzoom.jpg?center=-1.7548776662,+0&zoom=5e-2), le serveur renverrait l'image entièrement calculée que le navigateur aurait juste à afficher. Pour permettre à l'utilisateur de sélectionner un endroit où zoomer, on pourrait utiliser l'attribut ismap (sur une image) en HTML, qui demande au navigateur d'envoyer au serveur les coordonnées (en pixels au sein de l'image) où l'utilisateur a cliqué, que le serveur pourrait ensuite convertir en coordonnées mathématiques et utiliser pour renvoyer (par une redirection HTTP) vers l'image correctement zoomée. Le système ainsi créé fonctionnerait sans aucun JavaScript, mais au prix d'une complexité considérablement accrue côté serveur puisque c'est lui qui doit faire tous les calculs (et aussi au prix d'une fuite d'information : le serveur a connaissance de tout ce que tout le monde décide de regarder).
  • Dans une version dynamique purement côté client, le serveur aurait une unique page Web à envoyer, qui contiendrait essentiellement juste du code JavaScript capable de calculer l'ensemble de Mandelbrot, mais aussi toute l'interface utilisateur permettant de cliquer ici ou là et de zoomer sur la région correspondante. Il s'agit là d'un véritable programme s'exécutant au sein du navigateur client, ayant beaucoup plus de possibilités d'interface que ce qu'on peut faire côté serveur, mais qui ne fonctionnera qu'en présence de JavaScript.

En réalité, les choses sont rarement aussi tranchées : certaines choses ne peuvent se faire que côté serveur (car, après tout, sauf cas d'une application purement autonome comme un calcul mathématique ou un jeu en monde clos, c'est le serveur qui a accès aux données qu'on veut afficher), d'autres choses ne peuvent se faire que côté client (car c'est le navigateur qui a accès direct à ce que l'utilisateur saisit comme commandes, mais aussi à des choses comme la taille de la fenêtre), et enfin certaines peuvent être mises d'un côté ou de l'autre (par exemple tout ce qui est relatif à la présentation ou la construction du HTML). De nos jours, JavaScript est essentiellement indispensable à un usage du Web et le plus possible de choses sont effectuées côté client.

Plutôt que l'exemple un peu artificiel d'un calcul d'images mathématiques, je devrais plutôt prendre celui d'un forum de discussion :

  • Les forums de discussion des années 2000–2010 étaient presque entièrement réalisés en « dynamique côté serveur » (typiquement dans le langage PHP) : le serveur est capable de produire toutes sortes de pages montrant, par exemple, un fil de discussion, la liste de tous les sujets du forum, la liste de tous les messages récents, de tous les messages de tel ou tel utilisateur, ce genre de choses (les paramètres de requête servant, à chaque fois, à préciser ce qu'on veut voir) : la page renvoyée par le serveur est, à chaque fois, une page HTML complète, ne nécessitant pas ou peu de JavaScript, qui montre les messages en question. Le peu de JavaScript éventuellement utilisé l'est surtout pour aider à la saisie d'un message (par exemple, en cliquant sur un emoji on déclenche un bout de JavaScript qui va saisir quelque chose comme :mrgreen: dans le formulaire d'entrée de texte, qui est un code interne compris par le serveur et remplacé par ce dessin dans le message).
  • Les réseaux sociaux modernes utilisent beaucoup plus de « dynamisme côté client » : le serveur ne va pas renvoyer de pages HTML toutes faites (ou alors elles sont extrêmement minimales — et moches — et destinées à l'indexation par les moteurs de recherche) mais plein de JavaScript qui va réinterroger le serveur pour demander, par exemple, le contenu d'un message (non pas en HTML « bon à afficher » mais dans un format spécifique à la transmission de données, comme XML ou, de plus en plus souvent, JSON), et c'est ce JavaScript qui va créer toute la décoration autour.

Généralement parlant, on tend à laisser au client tout ce qui est présentation et décoration : le JavaScript va demander des données « brutes » au serveur et se charger de toute la mise en forme, tout l'affichage, toute l'interface utilisateur. (La même répartition tend à valoir pour les applications mobiles, car le site Web, ou plutôt l'application Web est souvent vu sur le même plan qu'une application Android et une application iOS.) Mais la répartition des tâches entre serveur et client n'est pas figée, et chaque concepteur de site Web doit faire des choix adaptés à ses buts et ses moyens : on trouve encore des forums de discussion largement réalisés « côté serveur », par exemple (et je ne parle pas là que du système de commentaires complètement archaïque qui sert encore sur ce blog).

J'avoue ne pas savoir, par exemple, quand Google Maps renvoie un itinéraire entre deux points, si le calcul de l'itinéraire est entièrement effectué côté serveur (i.e., chez Google), ou en partie dans le navigateur qui l'interroge et sur la base des données fournies par Google. (L'application mobile Google Maps a forcément une partie de capacité de calcul d'itinéraires côté client car on peut l'interroger même sans accès au réseau, si on a préchargé les cartes ; a contrario, Google Maps dans un navigateur ne peut rien afficher sans JavaScript.)

Ce dynamisme finalement partagé entre client et serveur fait que l'affichage de la moindre page du Web moderne conduit à un dialogue extrêmement complexe entre client et serveur (le client demande une première page, qui contient du JavaScript qui va redemander plein de données au serveur, des images et animations, des polices de caractères, d'autres bouts de JavaScript, y compris chez d'autres serveurs, sans parler des mouchards publicitaires et compteurs de vues). On peut s'en rendre compte en allant dans l'onglet réseau des outils de développement du navigateur (au moins chez Firefox, mais je suppose que Chrome a l'équivalent) : pour afficher un bête fil Twitter, par exemple, je vois passer plus de 200 requêtes HTTP, et pour une recherche Google de mon nom, j'en vois plus de 100.

Le dynamisme côté client a aussi comme conséquence que la partie « fragment » de l'URL (celle qui commence par ‘#’, j'en ai parlé plus haut) a largement dépassé sa fonction initiale de faire un lien à l'intérieur d'une page : elle peut servir à toutes sortes de paramètres côté client : contrairement au serveur, qui n'a connaissance de la partie qui précède le ‘#’, le JavaScript côté client peut lire la totalité de l'adresse demandée, fragment compris, et s'en servir pour modifier ce qui est affiché de la même manière que les paramètres de requête (dont j'ai aussi parlé plus haut) peuvent servir côté serveur. C'est le cas, par exemple, sur OpenStreetMap : une adresse comme https://www.openstreetmap.org/#map=12/48.8623/2.3309 indique dans la partie fragment l'emplacement et le niveau de zoom de la carte à afficher, et c'est le JavaScript (toujours le même !) récupéré à https://www.openstreetmap.org/ qui va lire ces informations et demander au serveur les bouts de carte à afficher.

D'autres choses en vrac

J'ai essayé de faire le tour de diverses technologies Web, du serveur au client, du HTTP au HTML+JavaScript. Forcément il y a des choses que j'ai oubliées au passage ou que je n'ai pas trouvé à quel point insérer. Essayons d'évoquer rapidement certaines d'entre elles.

Les redirections HTTP

Une redirection HTTP est un moyen de déplacer une page Web sans casser les liens qui pointaient vers elle.

Ceci est sans doute plutôt une note que j'aurais dû écrire quelque part, mais je ne sais pas bien où.

Au lieu de renvoyer un document, un serveur Web peut aussi renvoyer une redirection, c'est-à-dire techniquement un code 301 Moved Permanently (ou 302 Found si la redirection n'est que temporaire) : cette réponse est accompagnée non pas d'un contenu mais d'une nouvelle adresse vers laquelle le navigateur est prié de « sauter ». Ceci permet de modifier l'adresse d'une page Web (i.e., la déplacer) tout en la gardant accessible depuis l'ancienne adresse, un peu comme un suivi de courrier à la poste (et à la différnence du code 410 Gone qui signifie parti sans laisser d'adresse).

Le corollaire de tout ça est qu'il n'y a pas de vraie excuse pour qu'une réorganisation d'un site Web casse des liens, en tout cas pas si les pages sont toujours disponibles (sous un autre nom ou selon une autre organisation) : une réorganisation bien faite devrait prévoir toutes les redirections pertinentes pour que les pages restent accessibles à leur ancienne adresse.

Il est aussi possible, plutôt que de faire une redirection, de fournir le même fichier à deux adresses différentes (après tout, la configuration du serveur permet essentiellement n'importe quoi : ce n'est pas comme si ça imposait de faire deux copies du fichier !). Mais c'est généralement une mauvaise idée, parce que les moteurs de recherche vont indexer la page en double, contrairement à une redirection, qu'ils vont traiter de façon intelligente.

Le HTTPS

Le HTTPS est la version sécurisée (chiffrée et signée) du HTTP : j'explique brièvement ce qu'il permet mais surtout ce qu'il ne permet pas.

Le HTTPS est une version chiffrée et signée du HTTP. C'est-à-dire que le client, après avoir contacté le serveur, va demander à celui-ci de certifier qu'il est bien qui il prétend être, puis va construire une clé cryptographique en commun avec lui, et va utiliser cette clé pour chiffrer toutes les données échangées. (Je renvoie à ce billet récent pour un peu de vulgarisation sur la cryptographie en général.)

En soi c'est très bien : que les données soient chiffrées est une protection contre leur espionnage par les agents intermédiaires ou personnes tierces (fournisseurs d'accès Internet, ou quiconque aurait accès au réseau), et la signature devrait être une protection contre l'usurpation d'identité. Avant d'envoyer un mot de passe, un code d'accès ou quoi que ce soit de confidentiel sur le Web, la moindre des choses est de vous assurer que la communication se fait en HTTPS (adresse commençant par https://, ce que votre navigateur rappellera, parce qu'il suppose que vous êtes un imbécile qui ne sait pas lire, par la présence d'un petit cadenas à côté de l'adresse).

A contrario, je considère que HTTPS n'a pas de raison d'être pour des pages publiques sans aucun élément confidentiel comme, par exemple, Wikipédia ou ce blog : on avance parfois comme raison que cela empêche que des tiers puissent savoir ce que vous consultez, mais en fait c'est faux, il y a beaucoup trop de fuite d'information (dans l'IP du serveur consulté, dans la longueur des requêtes, etc.) pour qu'on puisse considérer que HTTPS offre cette protection ; on avance aussi parfois comme raison que cela empêche l'insertion d'éléments malicieux dans les pages (par exemple d'éléments publicitaires), et c'est vrai, mais si votre fournisseur Internet vous joue des crasses comme ça vous devriez de toute façon passer par un VPN ou quelque chose de ce genre (et accessoirement, c'est une grave faute de conception du HTTPS de ne pas avoir prévu de moyen de faire de la protection d'intégrité sans chiffrement).

En revanche, HTTPS a toutes sortes d'inconvénients : il détruit, par exemple, la possibilité des caches Web (même de données publiques). Mais aussi, il place le Web sous la coupe d'un système mafieux (s'ajoutant à celui déjà existant sur la vente des domaines DNS) car des erreurs de conception profondes du HTTPS empêchent qu'on puisse chiffrer sans authentifier (alors que c'est conceptuellement parfaitement possible), ou encore authentifier sur la base des précédentes consultations du site Web (ce qui est la chose naturelle qu'on devrait faire, car ce qui importe avant tout à un utilisateur est de savoir si un site Web est bien celui auquel il pense, c'est-à-dire celui qu'il a l'habitude de consulter), du coup pour pouvoir utiliser HTTPS il faut se placer sous la protection d'un parrain mafieux qu'on appelle une autorité de certification, qui vous fait payer pour accepter de dire que vous êtes bien le serveur du nom de domaine renvoyé par le DNS (et rien de plus). Récemment est apparu une autorité de certification moins mafieuse que les autres, du nom de let's encrypt, qui a rendu le HTTPS conceptuellement utilisable par tous, mais il demeure de graves problèmes techniques (par exemple le fait que si let's encrypt disparaît, ou simplement si vous n'arrivez pas à le contacter pendant un certain temps, votre site Web disparaît avec lui) qui me semblent assez rédhibitoires pour un site tel que le mien. (Je parle plus en détail de mes reproches à HTTPS dans ce billet. Mais encore une fois, je ne prétends pas qu'il n'est pas utile en général : si vous voulez échanger des données confidentielles, le HTTPS est indispensable, il serait par exemple inconcevable qu'un site bancaire, ou médical, ou quelque chose comme ça, ne passe pas par HTTPS ; c'est pour Wikipédia ou un blog que je trouve que c'est une erreur de s'en servir.)

En tout cas, il faut que je sois parfaitement clair : HTTPS ne garantit en rien que le site auquel vous vous connectez est bien celui auquel vous pensez, et certainement pas que ce site n'est pas malicieux, il vous garantit juste que le site auquel vous vous connectez est celui qui est écrit dans la barre d'adresse, et c'est tout. (Bon, certificats dits à validation étendue vont aller vérifier si la raison sociale légale de l'organisme au nom duquel ils sont établis. Enfin, si les autorités de certification font leur travail, ce qui est un peu douteux.) Rien n'empêche quelqu'un qui cherche à vous soutirer vos codes d'accès bancaires de créer un site Web visuellement identique à celui d'une banque bien établie en prenant un nom de domaine quasiment identique à un caractère près, et d'obtenir un certificat pour ce domaine (même un certificat à validation étendue s'ils ont créé une compagnie à ce nom aux îles Caïman ou quelque chose de ce genre). Donc le HTTPS assure la confidentialité des données mais absolument pas l'honnêteté de la personne en face, ni même son identité sauf dans le sens très précis de la coïncidence avec le nom de domaine que votre navigateur affiche et qui n'est pas forcément celui auquel vous pensez. Une fois de plus il faut toujours regarder avec soin l'adresse de la page qu'on consulte.

De tout autre point de vue, le HTTPS fonctionne pareil que le HTTP : la seule différence est l'adresse en https:// au lieu de http:// ; théoriquement, ce sont des adresses complètement distinctes, les pages https://www.example.tld/some/where.html et http://www.example.tld/some/where.html peuvent montrer des choses complètement différentes et sans rapport l'une avec l'autre ; en général, on configure les serveurs Web soit pour rediriger de l'une vers l'autre (ce qui oblige les utilisateurs à passer par HTTPS même s'ils n'en ont pas envie, ce que je trouve insupportable), soit pour renvoyer le même contenu (ce qui pose un problème d'indexation par les moteurs de recherche, parce que, en principe, ce sont bien deux sites complètement distincts qui renvoient le même contenu, et les liens vers l'un ou vers l'autre n'ont aucun rapport). C'est là aussi quelque chose que je considère comme une faute de conception du HTTPS de ne pas avoir imposé de contrainte à ce sujet.

Quelques mots sur la sécurité JavaScript

Le JavaScript est un langage extrêmement puissant, mais avec cette puissance vient le danger de toutes sortes de bugs dans le navigateur.

J'ai expliqué que JavaScript était un langage de programmation permettant de faire tourner des programmes essentiellement quelconques au sein du navigateur client. Mais bien sûr il doit exister toutes sortes de limite sur ce qu'un programme JavaScript a le droit de faire : par exemple, il n'a pas le droit de lire vos fichiers (sinon en consultant, disons, Facebook, votre navigateur exécuterait du code JavaScript écrit par les gens de Mark Zuckerberg, qui aurait le droit de fouiller dans vos fichiers et renvoyer toutes vos données personnelles à Facebook… manifestement on ne veut pas ça).

Le code JavaScript est donc censé s'exécuter dans un bac à sable, c'est-à-dire qu'il n'a le droit de faire que des choses bien précises (lire ou écrire les données relatives au domaine que vous êtes en train de consulter, modifier la page que vous voyez mais pas les autres, exécuter des calculs mais avec des limites en temps d'exécution et en mémoire, ce genre de choses). Ces limites sont complexes à définir, et surtout très complexes à imposer, parce qu'on est toujours pris dans le dilemme que le moteur JavaScript doit être à la fois très rapide et capable de vérifier que tout ce que le code effectue est légitime selon les règles de sécurité (ceci est rendu encore plus complexe, par exemple, par le fait que le code JavaScript peut lancer des calculs sur la carte graphique, ce qui est nécessaire pour du rendu 3D efficace, laquelle a un modèle de sécurité bien différent).

Régulièrement, on découvre des bugs dans les moteurs JavaScript des principaux navigateurs qui permettent au programmes JavaScript de contourner les limitations que le langage est censé maintenir, et, du coup, de faire essentiellement n'importe quoi sur l'ordinateur qui les a lancés (← ceci est très mal), ou d'utiliser diverses formes de fuite d'information pour espionner d'autres programmes sur l'ordinateur sur lequel ils tournent (← ceci est un petit peu moins mal mais quand même très problématique, et surtout beaucoup plus compliqué à éviter). La raison technique détaillée est que programmer est très dur, surtout quand on doit maintenir en permanence l'efficacité du JavaScript et ses règles de sécurité très complexes. Je n'ai malheureusement pas de bon conseil à donner ici à part de mettre à jour très régulièrement le navigateur qu'on utilise (et oui, les mises à jour sont très fréquentes, et sont largement liées à des problèmes de sécurité dans JavaScript).

Le canvas du HTML5

Le canevas du HTML5 est un élément dans lequel on peut « dessiner » en JavaScript, ce qui a été une façon importante d'ouvrir la porte de pages dynamiques graphiques et Web applications en tous genres.

Un certain nombre d'améliorations apportées par le HTML5 sont, en fait, plutôt liées au langage JavaScript qu'au HTML lui-même (ou disons qu'elles concernent l'interaction entre les deux). L'élément le plus emblématique à ce sujet est la balise <canvas> ou canevas : sans JavaScript, cet élément n'a aucun intérêt, il se présente comme un simple rectangle gris (comme une image, mais toute grise). Mais l'intérêt du canevas est qu'il s'agit d'une image modifiable par le JavaScript, c'est-à-dire que le programme JavaScript qui tourne côté client peut dessiner librement dedans (tracer des traits, des formes, du texte, mais aussi des choses beaucoup plus compliquées comme des images 3D rendues par une interface spéciale appelée WebGL et dont je ne mentionnerai que le nom, qui bénéficie de l'accélération fournie par le matériel graphique moderne).

De nombreuses pages Web ne comportent quasiment pas de HTML, essentiellement juste un élément canvas prenant la quasi totalité de la page, et c'est ensuite du JavaScript qui va réaliser tout l'affichage graphique à l'intérieur de ce canevas comme si c'était l'écran d'un ordinateur ou d'une tablette mobile. C'est le cas de Google Maps, par exemple : les éléments d'interface comme les menus de réglage ou la barre de recherche sont du HTML, mais la carte elle-même est simplement une image dessinée par du JavaScript sur un élément canvas aussi gros que la fenêtre du navigateur.

Dans le même genre, le HTML5 inclut également des éléments audio et video qui permettent respectivement de jouer du son et des vidéos mais en étant normalement en lien avec du JavaScript qui va contrôler cette lecture (démarrer la lecture, la mettre en pause, positionner le son ou la vidéo à un moment donné, appliquer des effets sonores ou visuels, etc.). Bref, comme canvas, il s'agit d'éléments HTML qui ont certes un sens tout seul mais ont surtout un intérêt quand ils sont utilisés en lien avec JavaScript.

Le HTTP est « sans état » ; les cookies

Le Web est conçu de façon amnésique, c'est-à-dire que chaque requête n'a aucune mémoire des requêtes précédentes. Un cookie est simplement une petite quantité d'information que serveur Web demande au navigateur client de lui rappeler lors des requêtes ultérieures. Dans cette section, j'évoque les raisons légitimes d'utiliser des cookies, mais aussi les problèmes qu'ils peuvent causer (en finissant par le cas particulier des cookies tiers).

Une des limitations du « Web à papa » est qu'il est « sans état ». Cela signifie que chaque fois que le navigateur demande une page Web, il fournit comme seule information au serveur Web qu'il interroge le chemin de la page demandée (paramètres de requête inclus), mais aucun « contexte général » : dans ce premier modèle du Web, si Alice et Bob consultent la même adresse en même temps, ils obtiendront le même résultat (enfin, sauf si le serveur décide de faire une réponse aléatoire, ou dépendant de l'adresse IP du client, ou quelque chose comme ça, mais en tout cas il n'a pas de moyen fiable de différencier Alice et Bob). C'est ennuyeux sur des sites où on pourrait vouloir s'authentifier, se connecter à un compte, ou simplement personnaliser quelque chose, ou même, simplement, maintenir une session (retenir quelque chose sur quelques pages d'affilée ; imaginez par exemple un questionnaire à remplir où on ne veuille pas mettre toutes les questions sur une seule page, mais on veut quand même rassembler les réponses d'une page avec celles de la page précédente et de la même personne, l'ennui étant que HTTP ne permet pas de façon évidente de donner un sens à même personne).

Un cookie est simplement une petite quantité d'information que le serveur demande au navigateur client de stocker de son côté, et de lui représenter à la prochaine requête, comme une façon de dire coucou, je suis toujours la même personne. Le cookie n'identifie rien du tout sauf si l'utilisateur a fourni des éléments d'identification : c'est une information envoyée par le serveur à lui-même, mais qui transite temporairement par le client et qui permet de relier deux requêtes comme venant du même client.

Si on veut, on peut imaginer qu'un serveur Web est profondément amnésique, à chaque fois qu'on lui parle il faut lui rappeler où on en est dans la conversation : les cookies servent à ça.

Le cookie sert en deux phases : le positionnement est la phase initiale où le serveur demande au navigateur client de créer un cookie et de lui donner une certaine valeur ; et ensuite, l'envoi va concerner chaque requête que ce navigateur fera sur ce serveur (au sein d'un profil utilisateur ou d'une session privée), c'est-à-dire que dans la requête HTTP que le navigateur fera, il rappellera au serveur au fait, vous avez positionné un cookie à telle valeur. Le positionnement peut éventuellement être limité dans le temps (c'est-à-dire que certains cookies s'effacent tout seuls à une certaine date), et/ou limité à une session active du navigateur (c'est-à-dire que certains cookies s'effacent tout seuls dès qu'on ferme ou relance le navigateur). Les cookies, par ailleurs, sont compartimentés à un domaine Web, c'est-à-dire que chaque site Web reçoit uniquement les cookies qu'il a lui-même positionné, pas ceux positionnés par d'autres sites (ceci pour éviter que n'importe quel site Web que vous consultez puisse connaître votre identifiant sur Facebook, Twitter, etc.).

Il y a un million de raisons légitimes d'utiliser des cookies dans un site Web : par exemple, pour retenir une préférence de l'utilisateur (si un site est disponible en plusieurs versions, ou plusieurs présentations, un cookie pourra servir à retenir celle que l'utilisateur préfère : ce cookie sera positionné au moment où l'utilisateur indique sa préférence, et ensuite il sera renvoyé au serveur qui en tiendra compte pour ajuster la page qu'il sert). Ou pour permettre de se connecter à un compte (le cookie sera positionné au moment où l'utilisateur se connecte au compte et que le serveur a vérifié son mot de passe, et ensuite il sera renvoyé au serveur pour indiquer le compte auquel l'utilisateur est connecté ; il faut bien sûr un élément de sécurité cryptographique dans le cookie pour qu'on ne puisse pas simplement envoyer un cookie disant bonjour, je suis Jean Dupont avec une requête et accéder ainsi au compte de Jean Dupont). Ou pour un état dans un site marchand (il est évident que pour maintenir un panier d'achats de la sélection d'un article jusqu'à son paiement il faut bien retenir qu'on a affaire à la même personne, donc un cookie).

L'alternative aux cookies, consiste à stocker un numéro de session dans l'adresse Web elle-même, sous forme de paramètre de requête : en gros, dès votre premier accès au site Web vous allez être redirigé vers la même adresse avec quelque chose comme ?sessionId=c41d5c9ab93dc331b2fa7ea1ff16ec39aeba01b8 ajouté à la fin, où le numéro est un numéro de session qui sert au serveur à retenir qui vous êtes, et qui sera aussi ajouté à la fin de tous les liens vers le site lui-même. Le serveur peut alors stocker en lui-même des informations relatives à cette session, et tant que vous suivez des liens avec ce paramètre de requête vous êtes considéré comme relié à cette session, et ces informations s'appliquent. Ceci permet de faire en gros la même chose que les cookies sans aucun cookie, mais avec l'inconvénient que tous les liens vers le site doivent être affublés de cet encombrant paramètre de requête, et que l'information de session voyage avec lui. Notamment, si l'utilisateur ouvre deux onglets vers le même site (depuis, disons, un moteur de recherche), il aura deux sessions indépendantes. Plus problématique, s'il partage un lien (p.ex. sur les réseaux sociaux), l'information de session l'accompagne, par exemple pour un site marchand ceci est inacceptable parce que cela voudrait dire que quelqu'un qui partage le lien vers un produit partage aussi l'accès à son panier (et malheureusement, il est compliqué de dire aux gens vous pouvez partager ce lien, mais pensez à retirer le paramètre sessionId avant de ce faire).

Mais bien sûr, le Web étant un grand far west, les cookies servent aussi à fliquer les utilisateurs : beaucoup de sites Web vont positionner des cookies qui ne servent absolument pas à retenir vos préférences ou à vous connecter à un compte, simplement à retenir qui vous êtes d'une visite à l'autre, et ainsi essayer de vous profiler (par exemple pour personnaliser des pubs). Ce sont les cookies indésirables. Or il n'y a structuralement aucune façon de distinguer un cookie désirable ou indésirable à part se demander intelligemment est-il normal que ce site Web retienne quelque chose sur moi ? est-ce que la page que je consulte est personnalisée ?.

La chose raisonnable à faire serait que ce soit le navigateur qui permette de façon très simple de définir quels sites ont le droit de stocker des cookies chez lui et lesquels n'ont pas le droit (avec comme possibilité intermédiaire, raisonnable dans la plupart des cas, d'autoriser les cookies uniquement pendant 24h ou jusqu'à fermeture du navigateur, ou quelque chose de ce goût-là, ce qui permet de faire fonctionner un site marchand, mais ne permet pas un flicage trop facile). Comme c'est le navigateur qui est l'arbitre final de quels cookies sont retenus ou pas, c'est la façon évidente de procéder. Et de fait, les navigateurs permettent quelque chose de ce genre.

Mais comme le Web semble aussi fonctionner sur le principe que les gens sont des cons (et ignorants, par exemple, des informations basiques que je décris dans ce billet), diverses juridictions, notamment l'Union européenne (Directive 2002/58/CE du Parlement européen et du Conseil), au lieu d'aider les navigateurs à informer et protéger les utilisateurs, ont plutôt imposé aux sites Web de demander un consentement explicite de l'utilisateur avant de stocker des informations à son sujet. Faire ça pour le moindre positionnement de cookie est une absurdité, et ce n'est pas, il me semble, ce qu'exige le droit européen : c'est une lecture maximaliste de l'article 5(3) de la directive (et passablement contradictoire avec le considérant (25) du préambule) que de s'imaginer qu'il faut un accord explicite pour positionner un cookie, il en faut un pour stocker des informations à son sujet, ce qui est assez différent.

Je soupçonne les sites Web de faire exprès de demander l'autorisation sans arrêt, pour que les utilisateurs soit las et cliquent sur tout autoriser sans réfléchir. Ceci permet de mettre en échec le droit européen qui cherchait à protéger les utilisateurs (en le faisant passer pour bien plus idiot qu'il n'est) et, en même temps, que les utilisateurs ne se posent pas la question mais au fait, pourquoi ce site a besoin de stocker des cookies sur mon navigateur ?.

Vous avez parfaitement le droit d'effacer n'importe quel cookie positionné par un site Web sur votre navigateur, ou de les supprimer tous : ceci ne doit pas causer de dysfonctionnement (autrement que par une perte de mémoire de préférences, connexion à un compte ou ce genre de choses), car il arrive sans arrêt que les cookies soient perdus ou effacés pour toutes sortes de raisons. Apprenez à utiliser votre navigateur en la matière (ou des extensions à celui-ci), par exemple pour interdire à certains sites de positionner des cookies (ou tous sauf certains sites), ou pour demander leur effacement automatique dès que vous quittez ou relancez le navigateur, ou au-delà d'un certain temps. Je trouve que ça n'a aucun sens pour un site Web de demander une autorisation à ce sujet : ou en tout cas, ça n'a aucun sens de faire confiance à un site Web de respecter ce qu'on lui aura dit (p.ex., de ne pas utiliser de cookies) : c'est au navigateur de vous protéger en la matière, pas aux sites Web de faire des promesses.

En fait, bien sûr, les cookies ne sont que la partie émergée de l'iceberg. Ils servent à retenir de petites quantités d'information (jusqu'à 4096 caractères, ou quelque chose de ce genre, c'est trois fois rien), essentiellement de quoi stocker un nom de compte, quelques préférences, un numéro de panier ou de session sur un site marchand. Si on fait un jeu en JavaScript et qu'on veut permettre de sauvegarder la partie, il faut quelque chose de bien plus copieux qu'un cookie. Pour des données bien plus volumineuses, il y a un autre mécanisme : le local storage de JavaScript (qui permet, en gros, à du JavaScript de stocker des données essentiellement quelconques, parfois très grosses, sur le navigateur local). Pour une raison qui m'échappe assez, on en parle très peu, alors que le local storage permet tout ce que les cookies permettent, et bien plus, et qu'il est bien plus difficile à consulter dans les navigateurs.

Le mal incarné : les cookies tiers

Comme je l'explique ci-dessus, je n'ai rien contre les cookies en soi, et je trouve normal que les sites Web s'en servent (l'enjeu doit plutôt être la durée pendant laquelle ils sont positionnés : grosso modo je pense qu'on devrait avoir besoin de l'autorisation explicite de l'utilisateur pour dépasser 24h ou bien la fin de la session du navigateur).

Il y a cependant un type de cookie particulièrement malicieux, ce sont les cookies tiers.

Une requête tierce, c'est une requête effectuée vers un site Web différent de celui dont l'adresse est affichée dans la barre d'adresse du navigateur ; ceci se produit fréquemment, par exemple il est parfaitement possible, et admis par les règles du Web (même si c'est malpoli lorsque c'est fait sans prévenir), pour un site Web A d'utiliser une image directement reprise d'un autre site B, non pas en recopiant l'image, mais en mettant directement dans le HTML l'adresse de l'image sur le site original (B) : quand on consulte le site A, le navigateur va effectuer une requête « tierce » vers B (qu'on appelle donc le site tiers) ; c'est le cas pour toutes sortes de ressources partagées, par exemple Google propose un service consistant à référencer des polices de caractères sur leurs serveurs, qu'on peut utiliser dans n'importe quel site Web (dans ce cas, Google est le site tiers), et il en va de même de nombreuses bibliothèques JavaScript qui sont partagées par l'intermédiaire de sites tiers ; c'est aussi le cas de l'inclusion prévue d'un bout d'un site Web dans un autre (la balise HTML <iframe> est plus ou moins prévue pour ça, c'est-à-dire un moyen d'inclure un bout de HTML dans un autre bout de HTML), par exemple on trouve très souvent des bouts de Google Maps sur des sites autres que Google (de nouveau, dans cet exemple, c'est Google qui va être le site tiers) ; et c'est encore le cas, par exemple, de toutes sortes de services de pub, qui vont aller chercher les images publicitaires sur des sites tiers.

Noter que, sur tous ces exemples, le site tiers a connaissance du site « original » depuis lequel la requête trouve son origine : le navigateur lui donne cette information dans les en-têtes HTTP (c'est normal, ne serait-ce que pour permettre au site tiers de n'autoriser son usage/inclusion que depuis certains sites).

Un cookie tiers, c'est un cookie qui aurait été positionné par le site tiers et qui lui serait renvoyé lors d'une requête tierce.

Voici l'exemple supposément légitime des cookies tiers (personnellement je ne le trouve pas légitime) : un site Web veut vous permettre de partager rapidement un lien par les réseaux sociaux, et suppose que ses utilisateurs sont de gros fainéants qui n'ont pas envie de copier-coller l'adresse dans un Tweet mais veulent juste pouvoir cliquer sur un lien partager sur Twitter ou quelque chose comme ça ; il va donc inclure un bout de Twitter (probablement dans une iframe HTML), ce qui fait de Twitter un site tiers, et comme Twitter a besoin de connaître votre compte pour vous permettre d'envoyer un tweet, il y aura un cookie tiers associé à la connexion à ce compte.

Maintenant, on voit immédiatement le problème avec cette situation : vous allez sur, disons, un blog politique du Parti Extrême-Grotsenien, celui-ci prévoit « gentiment » sur sa page un petit gadget pour vous permettre de retweeter le manifeste du parti, qui fait donc appel à Twitter comme site tiers, et votre navigateur va donc effectuer une requête tierce vers Twitter, en lui fournissant le cookie qui permet à Twitter de connaître votre identité sur Twitter. Mais en même temps, cette requête indique l'identité du site original, c'est-à-dire le blog du Parti Extrême-Grotsenien. Et voilà que votre navigateur a révélé aux gens d'Elon Musk votre intérêt pour le Parti Extrême-Grotsenien, et on va donc vous servir des pubs dans ce sens. Et ce, même si vous n'avez pas choisi de tweeter quelque chose (évidemment si vous décidez de le faire, c'est normal et un peu inévitable que Twitter le sache, mais la requête tierce a lieu même sans ça).

Le navigateur ne va pas jusqu'à envoyer au site tiers les cookies du site original, bien sûr, car le compartimentage des cookies l'interdit. Néanmoins, il va quand même donner au site tiers l'information que tel utilisateur consulte tel site à tel moment, ce qui est une fuite d'information énorme.

La solution évidente, c'est d'interdire les cookies tiers, et je crois qu'à l'heure actuelle tous les principaux navigateurs soit ont sauté le pas, soit proposent au moins cette option. (Une option un peu moins radicale aurait pu être de sous-compartimenter les cookies tiers, c'est-à-dire que les cookies d'un site ne lui soient renvoyés que quand le site du cookie et le site d'origine de la requête coïncident tous les deux avec ce qu'ils étaient au moment du positionnement du cookie : cela permettrait quand même d'inclure des bouts de, disons, Twitter sur un autre site, mais il faudrait se reconnecter à son compte Twitter séparément sur chaque site depuis lequel on veut autoriser la manip.)

L'écosystème des navigateurs

Dans cette section, je déplore la tendance de l'écosystème des navigateurs Web a tendre vers un quasi-monopole d'un seul programme (autrefois Netscape, puis Internet Explorer, maintenant Chrome). J'évoque la manière dont le navigateur doit défendre la liberté de l'utilisateur face aux sites Web, et le danger que la domination d'un seul programme fait peser sur ce principe.

J'aurais sans doute dû évoquer l'histoire des navigateurs Web, et les transformations du paysage en la matière. En 1996, Netscape Navigator représentait quelque chose autour de 80% des clients Web. Même pas une décennie plus tard, en 2002, l'écosystème avait été bouleversé : c'est Internet Explorer qui avait un pourcentage comparable (Microsoft l'ayant fourni d'office avec Windows qui était le système d'exploitation très largement majoritaire sur les PC, cet abus de position dominante lui avait permis de convaincre énormément d'internautes de passer de Netscape à IE). Au cours des années 2003–2012 environ, la part de marché d'IE s'est effritée en faveur d'autres navigateurs, notamment Firefox (logiciel libre né de façon compliquée des cendres de Netscape Navigator à travers le projet Mozilla). Et depuis 2012, c'est au tour de Chrome, le navigateur développé par Google, de profiter à son tour d'un abus de position dominante de Google (cette fois, sur le marché des moteurs de recherche, mais aussi des mobiles à travers Android) pour se développer jusqu'à représenter une écrasante proportion des navigateurs. On en est donc environ au troisième ou quatrième navigateur (Netscape en 1996, IE en 2002, peut-être Firefox vers 2012, et Chrome maintenant) à dominer le marché de façon plus ou moins écrasante. (Je ne parle pas des époques encore plus anciennes, parce qu'on peut considérer qu'il n'existait même pas vraiment plusieurs navigateurs distincts.)

Même si la domination actuelle de Chrome n'est pas aussi complète que celle d'IE en 2002, c'est préoccupant. Évidemment, les guerres des navigateurs n'étaient pas une situation idéale (la guerre Netscape-IE s'est traduite par une floraison d'incompatibilités pénibles dans l'interprétation du HTML et d'autres normes), mais l'hégémonie d'un seul logiciel est plus problématique encore.

Actuellement, le Web est, à travers Chrome, largement dans les mains de Google : s'ils veulent tuer une technologie, il suffit qu'ils décident que Chrome ne la gérera pas : aucun site Web ne se servira de quelque chose qui n'est pas supporté par un navigateur représentant plus de 65% des clients ; et dès lors, il devient absurde pour un autre navigateur de chercher à continuer à maintenir cette technologie. Inversement, si Google décide d'intégrer quelque chose dans Chrome, de nombreux sites s'en serviront s'ils y trouvent un usage, et tous les autres navigateurs devront faire pareil, sauf à perdre encore plus d'utilisateurs. C'est ainsi que Firefox, dont la part s'érode de plus en plus, se retrouve essentiellement à courir derrière tout ce que fait Chrome, ce qui accentue sa position de second couteau, et forcément il n'attire pas plus d'utilisateurs car il n'a à offrir qu'une pâle copie de ce que fait Chrome. (La situation de Safari est un peu différente, parce qu'il est très lié à l'écosystème Mac, qui maintient ses utilisateurs dans un jardin clôturé, surtout sur mobile.) Je pense que Mozilla aurait intérêt à cesser de courir après Chrome et offrir quelque chose de vraiment différent sur les points où ils ont vraiment un avantage, par exemple un navigateur plus configurable pour l'utilisateur, mais le fait est qu'ils n'adoptent pas cette stratégie et sont réduits à courir après Chrome et finiront par ne plus avoir assez d'argent pour continuer le développement (or développer un navigateur Web coûte très très cher car il faut sans cesse réparer des trous de sécurité).

Ceci signifie aussi que quand une norme du Web est obscure, c'est l'interprétation de Chrome qui fera référence, et là aussi c'est préoccupant. C'est encore plus préoccupant que, en fait, Chrome et Edge (le successeur de Internet Explorer) utilisent le même moteur de rendu sous-jacent, et même Safari a la même origine : il n'y a que les dérivés de Mozilla qui représentent une véritable alternative dans le rendu HTML ou l'interprétation du JavaScript.

Je devrais donner l'exemple de XUL, une technologie très intéressante imaginée par Mozilla pour son navigateur (et ensuite pour Firefox, mais maintenant elle est en train d'être gelée et retirée) : l'idée était d'avoir et de pouvoir mélanger, en parallèle à HTML qui permet de faire des pages d'hypertexte, de MathML qui permet d'écrire des formules mathématiques, et de SVG qui permet de faire du dessin vectoriel, dans le même document, du XUL qui permet, lui, d'avoir des éléments d'interface graphique (menus déroulants, fenêtres, onglets, boutons et autres éléments d'interaction avec l'utilisateur) qui seraient gérés nativement par le navigateur au lieu de devoir être traités par du JavaScript dans chaque site Web : ce XUL serait (est ? était ? aurait été ? aurait eu été ? je ne sais pas bien où ça en est maintenant) disponible à la fois pour n'importe quel site Web (lui permettant de développer facilement une interface utilisateur) mais aussi pour des extensions au navigateur, et pour le cœur du navigateur lui-même. L'idée est extrêmement bonne, et elle a été tuée par la course après Chrome que Firefox s'est senti obligé de livrer. (Je crois que beaucoup de bouts de Firefox sont encore écrits en XUL, mais la possibilité de s'en servir pour écrire des extensions au navigateur a été tuée dans la fin des années 2010, et avec elle une bonne partie de la supériorité que Firefox avait sur Chrome.)

Je ne sais pas comment on peut régler ce problème et mettre fin à cette situation où le Web ne connaît qu'une succession de monopoles au lieu d'un écosystème sain. (En tout cas cela réfute certaines théories économiques selon lesquelles le libre échange non régulé éviterait naturellement la constitution de monopoles de fait.)

Un exemple du danger de la domination de Chrome : la Web Integrity

Pour illustrer le pouvoir maléfique dont dispose Google à cause de la domination de Chrome sur le marché des navigateurs, évoquons brièvement le projet Web Integrity dont j'entends parler via ArsTechnica (je ne sais pas si la menace se réalisera vraiment, mais c'est un exemple d'une possibilité menaçante).

Pour comprendre de quoi il s'agit, il faut se rendre compte que l'utilisateur a un assez bon contrôle sur son navigateur et sur ce que son navigateur fait : le site Web consulté demande au navigateur d'afficher certaines choses et de faire tourner certains programmes JavaScript, mais le navigateur est l'arbitre ultime de ce qu'il fait, et il devrait, et en l'état actuel c'est plus ou moins le cas, obéir en premier lieu à l'utilisateur qui le fait tourner et pas à la page Web affichée. C'est-à-dire que l'utilisateur peut modifier la page Web, modifier le JavaScript qui s'exécute, en invalider des bouts, en remplacer d'autres, etc. : ceci se fait par exemple à travers les outils de développement intégrés dans le navigateur, mais si l'utilisateur n'est pas techniquement compétent pour s'en servir, il peut exister diverses extensions au navigateur déployant des modifications soit générales soit spécifiques à tel ou tel site. Le plus évident est de bloquer des pubs, ou d'empêcher des bloqueurs de bloqueurs de pubs (et ce petit jeu pourrait continuer sur plus de niveaux), mais il y a toutes sortes d'autres choses qu'on peut faire avec un peu d'expertise technique en contrôlant le navigateur (télécharger une vidéo destinée à ne s'afficher que dans une fenêtre bien précise, par exemple, ou améliorer l'interface utilisateur de tel ou tel site ou réseau social, ou encore effectuer de façon automatique certaines actions répétitives). On appelle par exemple collectivement userscripts des bouts de JavaScript qui s'exécutent à la demande de l'utilisateur plutôt qu'à la demande de la page Web affichée, i.e., ajoutés a posteriori.

(Zut, je me rends compte que le paragraphe précédent est quelque chose de très important que j'aurais sans doute dû dire ailleurs, mais à ce stade je ne sais plus où le mettre.)

Comme je le suggère à diverses reprises ailleurs dans ce billet, les systèmes d'exploitation mobile (Android et iOS) donnent beaucoup moins de pouvoir à leur utilisateur que les navigateurs : vous ne pouvez pas modifier a posteriori une app Android/iOS pour en bloquer les pubs, pour ajouter des fonctions, etc. Au contraire, ces systèmes d'exploitation essaient de vous interdire de telles manips en mettant en place, par exemple, tout un mécanisme de chiffrement cryptographique des applications (ostensiblement au nom de la sécurité, mais en fait en bonne partie pour augmenter le contrôle sur l'utilisateur). C'est la raison pour laquelle beaucoup de sites essaient de vous persuader de les consulter via leur app mobile plutôt que via leur site Web. Mais bon, le propos de ce billet n'est pas vraiment de parler de mobiles.

L'initiative Web Integrity de Google, pour autant que je la comprends, vise, sous le prétexte fallacieux de la sécurité, à accroître le contrôle sur l'utilisateur côté sites Web pour l'aligner, sans doute, avec ce qui est possible côté mobile. Ceci peut signifier : empêcher les bloqueurs de pub, empêcher la modification du JavaScript, empêcher la modification du HTML, empêcher la suppression ou modification de cookies, empêcher les extensions anti-flicage, empêcher l'automatisation de tâches, etc. Il y a déjà des mécanismes de cette nature, les DRM, spécifiquement pour certains contenus (lecture de vidéos, essentiellement : il s'agit d'empêcher l'utilisateur de télécharger ou recopier la vidéo au vol), mais le projet dont on parle consiste essentiellement à étendre ça à l'ensemble du Web (les détails ne sont pas clairs à de stade).

Évidemment, pour qu'un tel projet ait une chance de réussir, il faut qu'il soit implémenté par les navigateurs. Et c'est là que ça ne peut marcher que grâce à la part de marché dangereusement dominante de Chrome : si Chrome ne représentait qu'une part modérée des navigateurs, aucun site Web ne pourrait décemment exiger la présence de la Web Integrity dans le navigateur, parce que ces sites ne fonctionneraient simplement pas sous l'immense majorité des navigateurs ; mais si Chrome implémente ça et que beaucoup de sites se mettent à dire nous en avons besoin pour fonctionner, ils peuvent ainsi asservir les utilisateurs en faisant croire que les autres navigateurs sont simplement techniquement en retard en ce qu'ils ne proposent pas cette fonction importante.

Je pense donc qu'il s'agit d'un excellent exemple du danger que représente le fait pour un navigateur d'avoir une position dominante sur le Web : peu importe que ce soit Google le grand méchant ici, ça aurait pu être, et par le passé ça a été, Microsoft ou quelqu'un d'autre, ce n'est pas l'enjeu, l'enjeu est que le Web a besoin de diversité pour espérer rester ouvert. La règle d'or pourrait être simplement : n'utilisez jamais le navigateur qui a plus de 50% de part de marché, s'il y en a un (et en l'occurrence, il y en a un, et c'est Chrome).

Il faudrait dire un truc sur les clients mobiles

Ici j'essaie de faire la distinction entre application mobile et application Web qui peut elle-même tourner sur un navigateur mobile, distinction qui n'est sans doute pas claire pour beaucoup d'utilisateurs (et je me rends compte que je n'explique moi-même pas bien…).

Il faudrait dire un truc sur les clients mobiles (c'est-à-dire tablettes et smartphones), mais je ne sais pas bien quoi.

Éclaircissons quand même, pour les gens pour qui ce n'est pas forcément évident, qu'il y a souvent deux façons d'accéder au même contenu sur mobile : par l'intermédiaire d'un navigateur, c'est-à-dire en passant par le site Web (qui peut ou pas avoir prévu une version spéciale mobile de son site, ou simplement avoir prévu qu'il ne s'affiche pas trop mal sur un écran de taille éventuellement assez petite), ou par une application sur le système d'exploitation mobile concerné (c'est-à-dire, dans la pratique, Android ou iOS), dite app. Parfois l'app est en fait une simple copie du navigateur mobile (ouvert sur le site Web visé) dans lequel on a coupé quelques fonctionnalités et ajouté quelques gadgets pour faire croire que c'est mieux. Dans énormément de cas, l'app mobile n'apporte pas grand-chose par rapport au site Web, mais comme elle permet de beaucoup plus fliquer et contrôler l'utilisateur (par exemple simplement l'empêcher de bloquer les pubs), parce qu'Android/iOS est beaucoup moins votre ami que votre navigateur, cf. la section précédente, les sites essaient souvent de vous harceler dans le but de vous persuader d'utiliser leur app : ce n'est pas pour vous rendre service, c'est pour leur rendre service à eux. Les apps mobiles qui ont vraiment un intérêt ce sont, par exemple, celles qui peuvent tourner en l'absence de réseau (et donc d'accès au Web).

Digression : Mozilla avait eu une excellente idée en tentant de développer un système d'exploitation mobile appelé Firefox OS : le principe fondateur aurait été d'abolir complètement la distinction (honnêtement sans intérêt) entre apps mobiles et sites Web tournant dans un navigateur (qui est lui-même une app mobile) : les apps de Firefox OS étaient écrites en JavaScript et le système d'exploitation mobile était essentiellement Firefox avec des extensions pour permettre notamment de stocker une app localement et d'accéder aux différents capteurs du téléphone (et de gérer un système de permissions essentiellement analogue à celui qu'Android a fini par adopter). Malheureusement, face à la puissance de la position dominante et préétablie d'Android (Google) et iOS (Apple), Firefox OS n'avait aucune chance sérieuse de pouvoir se tailler une part de marcher, malgré sa supériorité technique (et dans le pouvoir qu'il donnait à l'utilisateur), et il a fini par être abandonné.

Mais s'agissant d'un site Web consulté à travers le navigateur mobile, il y a très peu de différence (à part la taille de l'écran et le fait qu'un écran tactile ne se manipule pas comme une souris) entre mobile et PC fixe ou portable, donc je ne crois pas avoir énormément à raconter sur le sujet.

Le fonctionnement du Web moderne

Dans cette section j'essaie d'évoquer le fonctionnement du Web moderne par contraste avec le fonctionnement du Web à papa par lequel j'avais commencé ce billet, mais je me contente surtout d'évoquer la plus grande place donnée à JavaScript, qui peut transformer une page Web en une véritable « application Web ».

Je devrais écrire le pendant de ma section sur le fonctionnement du Web à papa pour décrire un peu, en synthétisant tout ce que j'ai expliqué plus haut, le fonctionnement du Web moderne, mais en fait celui-ci est beaucoup plus varié et compliqué à découper en morceaux que le Web à papa. (Et, il faut être honnête, quand je dis Web moderne, je ne suis pas du tout sûr d'être au courant des dernières innovations d'intérêt douteux. C'est peut-être plutôt le Web des années 2010, en fait.)

Certaines pages continuent à fonctionner assez largement comme dans les années 1990–2000, juste avec un HTML un peu enrichi et un peu plus de JavaScript pour rendre le contenu plus réactif. Mais beaucoup de pages prennent plutôt la forme de « Web applications » : le contenu renvoyé initialement par le serveur contient très peu de HTML (souvent gros juste un texte qui dira ce site a besoin de JavaScript pour fonctionner), et surtout des liens vers plein de bouts de JavaScript. Ces bouts de JavaScript vont s'exécuter sur le navigateur et charger plein d'autres choses : d'autres bouts de JavaScript, des images en tous genres servant à la présentation du site (icônes de navigation, ce genre de choses), et plein de données de toutes sortes, souvent au format XML ou JSON (ce dernier format est, en fait, une sorte de sous-ensemble de JavaScript servant à transporter uniquement des données sans aucun bout de programme). La page que l'utilisateur voit sera alors construite par le JavaScript : c'est-à-dire qu'il crée, en mémoire, du HTML virtuel, ou simplement des images dessinées par l'intermédiaire d'un élément canvas. Pour donner des exemples, comme je l'ai dit plus haut, Google Maps est essentiellement une application en JavaScript qui écrit dans un canvas pour dessiner l'image ; Twitter, lui, va construire du HTML à partir de données renvoyées par les serveurs au format JSON (contenant en gros le texte des tweets et l'indication de quoi cite quoi ou quoi répond à quoi).

Comme je l'ai suggéré plus haut, le même contenu va souvent être disponible par une interface triple : une application Web, une app Android et une app iOS (et rien n'empêche d'utiliser l'application Web sur mobile, même si on va souvent tenter de vous en dissuader pour de mauvaises raisons). Le fait de devoir maintenir ces trois versions en parallèle explique que souvent le site essaie de se simplifier la gestion du serveur : c'est-à-dire que les trois « applications » demanderont essentiellement le même contenu au serveur, au même format, et différeront simplement dans la manière dont ils l'affichent. C'est notamment cette idée de maintenir l'application Android et l'application iOS en parallèle de l'application Web qui fait que, souvent, le serveur ne renvoie pas du HTML mais quelque chose de plus « brut » (le format JSON étant assez populaire à ce sujet).

API ouvertes et scraping

Ici j'évoque la manière dont les serveurs communiquent les données brutes aux navigateurs par des API Web, qui peuvent être plus ou moins ouvertes ou documentées. J'explique notamment ce que cela signifie que Twitter et Reddit aient fermé leur API publique. Et je finis en évoquant la notion de scraping, c'est-à-dire la récupération automatisée de données d'un site Web sans autorisation explicite de sa part.

Je conclus cette bien trop longue entrée par une explication autour de la question des API et du scraping (avec une remarque sur les cas de Twitter et de Reddit).

Imaginez un réseau social, donc (mais ces considérations pourraient s'appliquer à plein d'autres types de site fournissant des données de toutes sortes) : la plupart de vos utilisateurs vont y accéder via le site Web ou une des apps mobiles que vous fournissez. Comme je le dis plus haut, en fait, le serveur va généralement fournir le même contenu aux différentes versions (interface Web et deux apps mobiles) : c'est-à-dire que l'interface, quelle qu'elle soit, va interroger le serveur HTTP par des adresses spéciales qui renvoient non pas du HTML directement à afficher, mais un contenu brut (souvent au format XML ou JSON, enfin, peu importe, un format aisément traitable informatiquement).

Par exemple, s'agissant d'un réseau social, on va pouvoir interroger le serveur pour lui demander la liste des derniers messages à montrer à l'utilisateur Machin (bon, déjà, pour commencer, il y a un mécanisme d'authentification permettant l'accès à ce compte), on va pouvoir lui demander le contenu du message numéro N et la la liste des réponses qu'il a reçues. La réponse du serveur va sans doute contenir le texte brut du message, des numéros d'attachements éventuels (images, vidéos, que sais-je encore), l'identité de l'auteur, la date dans un format informatiquement standardisé (peut-être exprimées en secondes depuis 1970), la liste des numéros des messages qui existent en réponse, le numéro du message parent ou peut-être de l'ensemble des ancêtres, le nombre de « likes » ou de votes ou ce genre de choses, bref, des renseignements standards associés à un message : mais toutes ces informations étant fournies sous une forme brute, aisément manipulable informatiquement, pas « bonnes à afficher », parce que le contenu bon à affiché devra être fabriqué à partir de ce contenu brut par l'app Web (en JavaScript), l'app Android (en Java) et l'app iOS (en Objective C) séparément, et sans doute un peu différemment dans chaque cas. Le serveur peut être plus ou moins directif dans ses réponses (selon les décisions du gestionnaire du site, il donnera peut-être une vue de toute une discussion, ou laissera l'app cliente fabriquer cette vue message par message), mais l'esprit est quand même toujours de confier à l'app les détails de l'affichage à partir de données brutes fournies par le serveur.

Ce mécanisme de communication s'appelle une API Web. Quasiment n'importe quel site qui existe sous forme d'une app Android et/ou iOS en plus d'un site Web (et pour peu que les apps ne soient pas juste une coquille mince autour du navigateur mobile) possède une API Web, au moins interne (c'est-à-dire exactement ce que je viens de décrire : un moyen commun aux différentes interfaces utilisateur d'interroger le serveur et obtenir de lui les données à mettre en forme).

Mais dès lors qu'on a mis en place une API Web interne, on peut s'interroger sur l'opportunité de l'ouvrir, c'est-à-dire de documenter la manière dont elle fonctionne et de laisser d'autres programmes obtenir les données que le serveur fournit.

Dans le cas d'un réseau social, cela permet par exemple de fournir des clients alternatifs au réseau social (une autre application Android, disons, qui permettrait de se connecter au même réseau, mais avec une interface différente, et des fonctionnalités légèrement différentes dans l'interface). Mais cela permet aussi d'opérer des « bots » sur le réseau social en question : des programmes qui se comportent comme un utilisateur du réseau social mais effectuent des tâches automatiques (répondre à certaines questions, poster régulièrement une certaine information, qu'il s'agisse d'une citation du jour ou de la température à Paris, ce genre de choses). Dans le cas d'un moteur de recherche, une API ouverte permet de faire toutes sortes d'études ou d'analyses à partir des résultats du moteur de recherche, ou d'intégrer la recherche dans d'autres applications, ce genre de choses.

Mais évidemment, les API ouvertes ont aussi de graves inconvénients pour les propriétaires du site : elles permettent aux utilisateurs de court-circuiter les pubs, par exemple (parce que les clients officiels vont insérer les pubs séparément du reste du contenu, l'API les présentera séparément, ou au moins en disant ceci est une pub, les clients alternatifs peuvent ne pas les afficher), elles diminuent le contrôle que les propriétaires du site ont sur leurs utilisateurs, et surtout, sur leurs données ; et elles font courir le risque de récupération importante de données par des sites tiers (un des enjeux, de nos jours, étant d'alimenter les données d'entraînement d'IA).

Un site peut donc mettre en place une API ouverte et gratuite mais nécessitant une inscription, et/ou limitée en volume (à un petit nombre de requêtes par jour, ou à certains types de requêtes) ; ou bien une API payante, ou les deux en parallèle, ou toute combinaison de tout ça. Ils ont plus ou moins forcément besoin d'une API à usage interne, et il est difficile d'empêcher de détourner cette API (il n'y a pas vraiment moyen d'authentifier un programme auprès d'un autre programme, donc pas vraiment moyen de savoir si le programme qui se connecte sur l'API à usage interne est vraiment un client officiel), mais divers moyens de rendre la chose plus compliquée.

Pour donner des exemples concrets, Google Maps a une API publique payante, mais ils proposent un essai gratuit pendant un an : je m'en étais servir pour récupérer des stats de temps de parcours entre chez moi et mon bureau (interrogation toutes les 20 minutes pendant un an). Twitter avait une API publique gratuite (avec des limites raisonnables) avant son rachat par Musk, qui permettait de faire tourner toutes sortes de bots mais aussi de clients alternatifs, et qui me permettait, à moi, de récupérer semi-automatiquement tous les tweets que j'écris pour tenir à jour cette archive (mais je m'en servais aussi pour poster automatiquement certains longs fils) : Musk a fait fermer cette API (c'est une des très nombreuses mesures qu'il a prises et qui ont dégradé l'état et l'utilisabilité de Twitter, en l'occurrence en faisant fuir toutes sortes d'utilisateurs qui passaient par des clients tiers), sous prétexte qu'elle servait à voler des données. Pour ma part, pour continuer à maintenir l'archive de mes tweets (dont je fais une précondition au fait de rester sur Twitter), j'ai basculé sur l'usage de l'API interne de Twitter, c'est-à-dire que je consulte régulièrement mes propres tweets en demandant au navigateur de sauver les échanges HTTP et j'ai ensuite des scripts qui sauvegardent et convertissent les tweets qui transitent par cet échange (voyez ici si vous voulez les détails, mais attention c'est très moche). Musk s'est inquiété que des gens venaient voler ses précieuses données par l'API interne, et il s'est mis à ajouter des limites même sur celle-ci, ce qui a précipité encore le déclin de ce réseau. Reddit (un autre réseau social de discussion et partage de liens) avait une API publique gratuite (idem, avec des limites raisonnables) et ils l'ont fermée parce qu'elle permettait de contourner les pubs : ceci a provoqué un grand mouvement de contestation sur le réseau social (et de grèves des modérateurs) parce que beaucoup d'utilisateurs étaient attachés à leur client alternatif. StackExchange (un réseau social en forme de questions-réponses) a une API publique gratuite (avec des limites raisonnables), et je m'en sers pour sauvegarder mes participations notamment à MathOverflow, et j'ai très peur qu'ils décident de la fermer aussi un de ces jours. Wikimédia (c'est-à-dire Wikipédia, Wiktionary, etc.) a une API ouverte évidemment, qui permet de faire des outils alternatifs pour consulter et éditer Wikipédia, mais aussi obtenir des statistiques sur les pages ou toutes sortes de choses du genre.

A contrario, un site qui n'a certainement pas d'API ouverte, c'est le site d'une banque : même s'ils ont des clients mobiles, et donc certainement une API interne, ils ne vont pas la documenter, et ils ne veulent certainement pas que vous vous en serviez, à la fois pour des raisons de contrôle, des raisons légales, et des raisons de sécurité, ils ne veulent pas que vous passiez par autre chose que leurs interfaces officielles pour accéder à vos comptes.

Pour résumer, les API Web, c'est souvent super, ça permet d'accéder à toutes sortes de contenus sans être prisonnier d'une interface Web (ou mobile) particulière, et ça permet d'automatiser plein de tâches (qu'il s'agisse d'interroger un temps de parcours sur Google Maps toutes les 20 minutes ou d'écrire un robot sur un réseau social). Mais pour différentes raisons, certaines assez bonnes (une banque), certaines épouvantablement mauvaises (Musk qui prétend qu'on va lui voler ses précieuses données), il peut y avoir une réticence à mettre en place une API ouverte.

L'alternative, c'est le scraping : scraper un site Web (i.e., le gratter) c'est l'interroger de façon automatisée sans avoir d'autorisation spécifique, en se faisant passer pour un navigateur Web. (Par exemple, scraper un site de dictionnaire, ça consisterait à lui demander tous les mots de la langue et les enregistrer, probablement dans un ordre un peu aléatoire, et en espaçant suffisamment les requêtes pour ne pas trop attirer l'attention.) Le scraping existe depuis le Web à papa, et on peut même dire que c'est un des fondements du Web puisque, après tout, ce que font les moteurs de recherche peut être assimilé à du scraping (sauf qu'en fait on a mis en place un système d'autorisation implicite, le fichier robots.txt, qui est chargé de dire aux moteurs de recherche ce qu'ils ont le droit de faire ou pas) ; mais le scraping prend une forme un peu différente dans le Web moderne, où on va souvent détourner une API interne (qui renvoie les données sous une forme brute, et la difficulté est de comprendre cette API et de trouver comment s'en servir) que dans le Web à papa (où les données seront renvoyées en HTML et la difficulté est surtout de dé-HTML-ifier ce qu'on veut, par exemple dans le cas d'un dictionnaire extraire juste les définitions des mots sans l'enrobage de la page Web).

↑Entry #2755 [older| permalink|newer] / ↑Entrée #2755 [précédente| permalien|suivante] ↑

[Index of all entries / Index de toutes les entréesLatest entries / Dernières entréesXML (RSS 1.0) • Recent comments / Commentaires récents]