HTTP/2
Introduction
Conçue par Tim Berners-Lee, la première spécification du protocole HTTP est disponible en 1991 dans la version HTTP/0.9, puis évolue vers HTTP/1.0 en 1996 et HTTP/1.1 en 1997. Pour rappel, la version HTTP/1.0 apporte de nouveaux verbes comme PUT et DELETE. Quant à la version HTTP/1.1, elle apporte le verbe OPTIONS permettant de faire des requêtes cross-domain, ainsi que l’en-tête Keep-Alive.
Depuis maintenant plusieurs années, le nombre de requêtes nécessaires pour télécharger un site web ne fait que grossir (tout comme les applications web, mais c’est un autre débat). Afin de ne pas dégrader l’expérience utilisateur, une nouvelle version du protocole HTTP est disponible depuis 2015, permettant de prendre en compte ces nouvelles contraintes.
Au fil du temps, le protocole HTTP évolue afin de s’affranchir des limitations des versions précédentes. Cela ne veut pas dire que toutes les bonnes pratiques décrites précédemment sont à jeter à la poubelle. Bien au contraire. Certaines d’entre elles sont toujours d’actualité pour optimiser le temps de chargement de l’application.
La mise en place de ces bonnes pratiques et l’activation du protocole HTTP/2 permettront d’optimiser le temps de chargement des navigateurs ne supportant pas les Service Workers...
Premiers pas avec HTTP/2
Pour tester ce protocole, nous allons utiliser le module nghttp. Ce module propose en ligne de commande une solution permettant de créer un serveur (via la commande nghttpd), mais également un client (via la commande nghttp).
Le module nghttp peut être installé sur l’ensemble des systèmes d’exploitation. Par exemple, sur Mac, via le gestionnaire brew.
brew install nghttp2
Une fois nghttp installé, nous avons à disposition les deux commandes citées précédemment.
Pour lancer un serveur HTTP/2 afin de servir le contenu d’un répertoire, nous exécutons la commande nghttp2. Dans l’exemple ci-après, nous souhaitons servir le contenu du répertoire dist, comparable au répertoire généré dans le chapitre Performances générales pour notre application, depuis un serveur supportant HTTP/2, mais sans connexion TLS, et via le port 8080.
nghttp2 --no-tls -d ./dist 8080
Pour faire une requête vers le serveur précédemment démarré, nous utilisons la commande suivante nghttp. Dans cet exemple, nous récupérons le contenu de la page page.html du répertoire dist.
nghttp http://localhost:8080/page.html
Nous pouvons voir que l’URL utilisée est identique à une URL du protocole HTTP/1.1. Cette rétrocompatibilité facilite...
Nouvelles fonctionnalités
Nous allons à présent décrire quelques nouveautés apportées par cette nouvelle version.
1. Format binaire
L’une des premières différences avec les versions précédentes est le format utilisé pour les requêtes et les réponses. En effet, dans les versions précédentes, nous manipulons des données au format texte, alors que le format actuel est plutôt du binaire.
2. TLS
Une autre caractéristique est l’utilisation d’une connexion sécurisée TLS. Ce critère n’est pas obligatoire, mais grandement recommandé. De toute façon, cela est devenu tellement simple de mettre en place des certificats SSL sur nos applications grâce à des solutions comme Let’s Encrypt, que toutes les applications devraient à l’heure actuelle être sécurisées. De plus, les moteurs de recherche favorisent les applications servies via une connexion sécurisée.
Si vous utilisez HTTP/2 avec une connexion sécurisée, vous verrez souvent le diminutif h2. Si la connexion n’est pas sécurisée, le diminutif sera h2c. Mais cela ne veut pas dire que l’ensemble des navigateurs respectent le protocole HTTP/2 sur une connexion non sécurisée. C’est pour cela qu’elle n’est pas préconisée.
Si nous tentons par exemple d’accéder au serveur créé précédemment (avec l’option no-tls signifiant que nous avons choisi le protocole h2c), Chrome retourne une erreur indiquant qu’il ne supporte pas ce protocole.
3. Multiplexage
Avec HTTP/1.1, lorsqu’une communication est établie (une connexion) entre un client et un serveur, nous devons obligatoirement attendre la réception de la réponse pour envoyer une nouvelle requête. À cela s’ajoute la limitation décrite dans le chapitre Performances générales concernant le nombre maximal de connexions simultanées que le navigateur peut ouvrir vers un même domaine.
Nous n’avons plus cette contrainte avec HTTP/2. En effet, grâce au multiplexage, une et une seule connexion vers le serveur est ouverte par le client, et toutes les requêtes sont envoyées...
Activation du protocole HTTP/2 avec Nginx
Bien évidemment, lorsque nous déployons de réelles applications en production, nous n’utilisons pas le module nghttp2. Ce dernier est réservé à un usage en local. En production, nous préférons des solutions reconnues comme Apache ou encore Nginx. Dans cette section, nous expliquons comment activer HTTP/2 avec Nginx.
Avant de configurer Nginx, il faut générer un certificat SSL obligatoire. Pour cela, nous pouvons par exemple utiliser un outil comme openssl. Nous ne rentrerons pas dans les détails de cette génération, une littérature détaillée est disponible sur Internet. Une fois cette action réalisée, deux fichiers sont créés que nous nommerons par la suite certificat.key et certificat.crt.
Une fois ces deux fichiers créés, il suffit de configurer Nginx. Pour cela, nous allons modifier son fichier de configuration dédié. Pour commencer, nous indiquons que nous écouterons sur le port HTTP 443 sur une connexion sécurisée utilisant le protocole HTTP/2. Ensuite, nous faisons le lien avec les deux fichiers précédemment créés.
Server {
listen 443 ssl http2;
ssl_certificate /etc/ssl/certs/localhost.crt; ...
Compatibilité navigateurs
Tous les navigateurs ne supportent pas encore le protocole HTTP/2. Mais cela n’est pas un problème, car le serveur, seul intervenant nécessitant une configuration pour activer HTTP/2, peut rétrograder la requête pour utiliser HTTP/1.1. C’est donc le navigateur qui indique quelle version du protocole il supporte et souhaite utiliser.
Le tableau suivant récapitule le support du protocole HTTP/2 par les navigateurs.
Le protocole HTTP évolue encore avec HTTP/3, se basant également sur des travaux de Google et son protocole QUICK. Cette nouvelle version apporte son lot de nouveautés, par exemple l’utilisation du protocole UDP plutôt que TCP.
Application fil rouge
Si nous souhaitons activer le support du protocole HTTP/2 sur notre hébergeur Netlify, nous n’avons en fait pas grand-chose à faire. En effet, Netlify supporte par défaut ce protocole. Nous pouvons vérifier le protocole utilisé via l’onglet Network des DevTools de notre navigateur.
Malheureusement, Netlify supporte HTTP/2, mais pas toutes ses fonctionnalités. Le multiplexage et la compression des en-têtes sont bien supportés. Mais cela n’est pas le cas pour la fonctionnalité de server push.
Si un jour cette fonctionnalité est disponible, il faudra a priori ajouter dans le fichier _headers spécifique à Netlify, les en-têtes HTTP correspondant aux ressources statiques que nous souhaitons pousser avec le fichier index.html. Dans l’exemple ci-après, le fichier script.js sera envoyé directement par le serveur à l’utilisateur visitant la page d’accueil du site.
/
Link: </script.js>; rel=preload; as=script
Afin de récupérer la correction de cette partie pratique, allez sur la branche Git chapitre_11.
git checkout chapitre_11