Je suis Charlie

Autres trucs

Accueil

Seulement les RFC

Seulement les fiches de lecture

Ève

RFC 2616: Hypertext Transfer Protocol -- HTTP/1.1

Date de publication du RFC : Juin 1999
Auteur(s) du RFC : Roy T. Fielding (Department of Information and Computer Science), James Gettys (World Wide Web Consortium), Jeffrey C. Mogul (Compaq Computer Corporation), Henrik Frystyk Nielsen (World Wide Web Consortium), Larry Masinter (Xerox Corporation), Paul J. Leach (Microsoft Corporation), Tim Berners-Lee (World Wide Web Consortium)
Chemin des normes
Première rédaction de cet article le 6 juin 2007


Pas besoin de présenter HTTP, un des protocoles les plus importants de l'Internet, en raison du succès du Web. Notre RFC était la norme officielle de HTTP, depuis remplacé par une série de huit RFC.

Le Web a beaucoup évolué depuis la sortie du RFC mais son protocole principal reste le même, HTTP 1.1. Contrairement aux normes portant sur le format des données, qui sont en général réalisées par le W3C, HTTP est une norme IETF. Le RFC est très long car, si HTTP est très simple dans son principe (ce qui a beaucoup aidé à son succès), il contient de nombreux détails (par exemple de nombreux en-têtes peuvent être transmis entre serveurs et clients pour des options variées) et je parie que peu de logiciels mettent en œuvre la totalité du RFC.

On notera aussi que, si HTTP est surtout connu pour permettre à un navigateur Web d'accéder à une page HTML, il peut aussi servir de protocole pour permettre à deux applications de communiquer, notamment en suivant l'architecture REST (voir programmation-rest.html et signaler-a-signal-spam.html pour des exemples REST). Ainsi, des protocoles comme IPP (RFC 2911) ou XCAP, XML Configuration Access Protocol (RFC 4827), utilisent HTTP (pas forcément en REST). Un RFC a même été écrit pour essayer de décrire dans quels cas il était souhaitable de réutiliser HTTP pour un protocole Internet, le RFC 3205.

Le protocole repose sur un mécanisme requête / réponse très simple (section 1.4). Le client se connecte en TCP au serveur, envoie une requête sur une seule ligne, la requête incluant un URI, éventuellement des options sous forme d'en-têtes analogues à ceux du courrier électronique (Accept: text/*), éventuellement un contenu, et reçoit une réponse sous forme d'un code numérique indiquant de manière non ambigüe le résultat de la requête, d'en-têtes optionnels et d'un corps, la ressource demandée.

Le terme de ressource est défini dans la section 1.3. Il est plus général que celui de page. Une ressource n'est pas forcément une page HTML, ce n'est même pas toujours un fichier.

Il existe plusieurs requêtes, définies en section 5.1.1. Les plus connues sont GET (récupérer une ressource, sans rien modifier), POST (modifier une ressource), PUT (créer une nouvelle ressource) et DELETE (comme son nom l'indique). Mais il faut noter que, si les applications REST, par définition, utilisent les différentes requêtes pour les différentes actions qu'elles peuvent effectuer, le navigateur Web typique ne connait que GET et POST. Et beaucoup d'applications ne sont pas REST, utilisant par exemple le POST comme un fourre-tout, l'action étant exprimée par un paramètre du POST et pas par la requête. C'est dommage, car la sémantique de chaque requête est rigoureusement définie par le RFC (voir particulièrement la section 9.1), notamment pour ce qui concerne les caches, l'idempotence et les invariants comme GET(PUT(x)) = x (en français : après un PUT, un GET du même URI doit donner la ressource transmise lors du PUT).

Les codes numériques de retour sont à trois chiffres, le premier chiffre indiquant la catégorie (2 est un succès, 4 une erreur dûe au client, 5 une erreur dûe au serveur, etc), comme avec SMTP. L'erreur la plus célèbre est sans doute la 404, « ressource non trouvée », décrite dans la section 10.4.5, qui se produit par exemple lorsqu'un webmestre n'a pas lu l'article Cool URIs don't change et a changé ses fichiers de place.

Il existe évidemment une pléthore de logiciels clients et serveurs HTTP, puisque les navigateurs Web et les serveurs comme Apache, parlent tous HTTP. Mais, pour apprendre le protocole, les clients en ligne de commande sont très pratiques. Ici, curl avec l'option --verbose permet de voir les requêtes envoyées par le client au serveur (elles sont précédées d'un signe >) et les réponses du serveur (précédées d'un signe <) :


% curl --verbose http://www.bortzmeyer.org/2616.html
* About to connect() to www.bortzmeyer.org port 80
*   Trying 80.67.170.20... connected
* Connected to www.bortzmeyer.org (80.67.170.20) port 80
> GET /2616.html HTTP/1.1
> User-Agent: curl/7.15.5 (i486-pc-linux-gnu) libcurl/7.15.5 OpenSSL/0.9.8c zlib/1.2.3 libidn/0.6.5
> Host: www.bortzmeyer.org
> Accept: */*
> 
< HTTP/1.1 404 Not Found
< Date: Wed, 06 Jun 2007 13:20:03 GMT
< Server: Apache/1.3.26 Ben-SSL/1.48 (Unix) Debian GNU/Linux AuthMySQL/3.1 mod_throttle/3.1.2 mod_watch/3.17
< Connection: close
< Transfer-Encoding: chunked
< Content-Type: text/html; charset=iso-8859-1
...

Ou bien, avec wget, son option --debug, et une ressource qui existe (dans le cas ci-dessus, le fichier n'avait pas encore été copié sur le serveur, d'où le résultat 404) :

% wget --debug http://www.bortzmeyer.org/1035.html
...
Connecting to www.bortzmeyer.org|80.67.170.20|:80... connected.
...
---request begin---
GET /1035.html HTTP/1.0
User-Agent: Wget/1.10.2
Accept: */*
Host: www.bortzmeyer.org
Connection: Keep-Alive
---request end---
...
---response begin---
HTTP/1.1 200 OK
Date: Wed, 06 Jun 2007 13:23:48 GMT
Server: Apache/1.3.26 Ben-SSL/1.48 (Unix) Debian GNU/Linux AuthMySQL/3.1 mod_throttle/3.1.2 mod_watch/3.17
Last-Modified: Wed, 30 May 2007 18:21:58 GMT
ETag: "2e6e69-19a6-465dc0c6"
Accept-Ranges: bytes
Content-Length: 6566
Connection: close
Content-Type: text/html; charset=utf-8

Afficher les en-têtes du dialogue entre le client et le serveur peut aussi se faire, si on utilise le navigateur Firefox, avec son extension « HTTP headers ».

Pour un exemple concret des options qui peuvent être passées au serveur via les en-têtes, prenons If-Modified-Since (section 14.25) qui permet au client d'annoncer au serveur « J'ai déjà une version de cette ressource, obtenue à telle date, ne me l'envoie que si tu as une version plus récente ». Par exemple, sur le site des étiquettes de langue, on a le registre dans divers formats. Ces formats sont produits localement, après avoir transféré le registre original. Celui-ci étant un gros fichier, on l'analyse pour trouver sa date et on utilise l'option --time-cond de curl pour générer un en-tête If-Modified-Since. Voici le script :

#!/bin/sh

MYURL=http://www.langtag.net/
LTR_URL=https://www.iana.org/assignments/language-subtag-registry
LTR_LOCAL=language-subtag-registry

if [ -e ${LTR_LOCAL} ]; then
  ltr_date=`head -n 1 ${LTR_LOCAL} | cut -d" " -f2`
  current_date=`date +"%Y%m%d" --date="${ltr_date} +1 day"`
else
  # Trick to force a downloading
  current_date="19700101"
fi
curl --verbose --output ${LTR_LOCAL}.TMP \
    --compressed \
    --referer ${MYURL} \
    --proxy "" \
    --time-cond "${current_date}" \
  ${LTR_URL}
...

Cela donne ceci, si le fichier n'existe pas (on a pris une date arbitraire dans le passé) :


...
> If-Modified-Since: Thu, 01 Jan 1970 00:00:00 GMT
> 
< HTTP/1.1 200 OK
< Last-Modified: Fri, 04 May 2007 18:36:16 GMT
< Content-Length: 80572

Si par contre le fichier existe et on a la version du 5 mars 2007, curl affiche :


...
> If-Modified-Since: Sat, 05 May 2007 00:00:00 GMT
> 
< HTTP/1.1 304 Not Modified
...

et le fichier n'est pas transféré.

Naturellement, si on veut développer un client HTTP, au delà de ce que permet curl (qui permet déjà beaucoup de choses), on dispose de nombreuses bibliothèques toutes faites comme httplib pour Python, libcurl (avec le programme du même nom) ou neon pour C, etc. HTTP est suffisamment simple pour qu'on puisse écrire rapidement un client, même sans ces bibliothèques comme le montre cet exemple en Python.

À noter que notre RFC utilise, pour décrire le protocole, une variante de l'ABNF standard, décrite en section 2.1, ce qui a suscité un certain nombre de problèmes.

Ce RFC 2616 a été remplacé en juin 2014 par une série de huit RFC, commençant par le RFC 7230. Le protocole HTTP 1.1 reste le même.


Téléchargez le RFC 2616

Version PDF de cette page (mais vous pouvez aussi imprimer depuis votre navigateur, il y a une feuille de style prévue pour cela)

Source XML de cette page (cette page est distribuée sous les termes de la licence GFDL)