Anatomie d'une requête HTTP
HTTP, pour Hypertext Transfer Protocol, est le protocole principal pour les échanges internet. Il est utilisé aussi bien par le navigateur que vous utilisez pour lire cet article, que pour faire communiquer des applications. Il s’appuie sur un éhange de requête et réponse, entre un client et un serveur, au format texte. L’avantage du format texte est qu’il est facile à implémenter dans tous les langages de programmation. Le protocole HTTP est spécifié par la RFC 2616, protocole dont la toute première version d’HTTP date de 1990.
Cet article traite de la version 1.1 du protocole, qui a été normalisée en 1997. Une version 2.0 a été normalisée en 2015, et étend la version 1.1 avec d’autres capacités. Les bases de la version 1.1 ne sont donc pas obsolètes !
Dans cet article, nous allons étudier la structure d’une requête et d’une réponse HTTP.
La structure d’une requête
Une requête est structurée en 3 parties :
- la ligne de requête, obligatoire, en première ligne
- les entêtes optionnels
- le corps de requête, lui aussi optionnel
REQUEST-LINE
[HEADERS]
[BODY]
Exemple de requête HTTP GET sans corps de requête :
GET /articles/http-anatomy?version=1#headers HTTP/1.1
Host: ekite.tech
Accept: text/plain
Accept-Charset: utf-8
Accept-Encoding: gzip
Accept-Language: fr-fr
Exemple comportant un corps de requête :
POST /articles/ HTTP/1.1
Host: ekite.tech
Content-Type: application/json
Content-Length: 31
Authorization: Basic UmljayBBc3RsZXk6TmV2ZXIgR29ubmEgR2l2ZSBZb3UgVXAK
{"title":"mon nouvel article"}
La Request Line
Les HEADERS et BODY sont facultatifs.
La REQUEST-LINE est définie de cette manière :
METHOD REQUEST-URI HTTP-VERSION
METHOD est le verbe HTTP. Il peut être GET
, POST
, PUT
, DELETE
, qui sont les verbes HTTP les plus courants.
La RFC 2616 définit aussi des méthodes supplémentaires, comme HEAD
, OPTIONS
, TRACE
, CONNECT
.
REQUEST-URI est la ressource à appeler. Elle peut être une URI absolue, comme https://ekite.tech/articles/http-anatomy
, ou une URI relative, comme /articles/http-anatomy
. En pratique, ce sont plutôt des URI relatives qui sont utilisées, en combinaison avec un Header Host
.
Le champ HTTP-VERSION
vaudra HTTP/1.1
.
Une requête HTTP minimale est :
GET /articles/http-anatomy HTTP/1.1
URL et URI
Une URI, pour Uniform Resource Identifier, définit une ressource internet. Cette ressource peut être une page Web, un document au format PDF, ou encore une vidéo.
Une URL, pour Uniform Resource Locator, est une URI particulière, qui contient les informations réseau pour accéder à une ressource. Les URI sont définies par un format texte composé de caractères ASCII.
La RFC 3986 spécifie les formats des URI.
La structure d’une URI absolue est :
SCHEME://HOST/PATH[?QUERY][#FRAGMENT]
Le SCHEME est souvent associé au protocole, http, https, ou encore file quand des fichiers locaux sont désignés.
Le HOST est le nom du serveur hébergeant la ressource.
Le PATH identifie le chemin vers la ressource.
La QUERY, aussi souvent appelé Query Strings, définit des paramètres supplémentaires que la ressource peut traiter, sous la forme name=value
.
Le FRAGMENT définit la partie de la ressource consultée.
QUERY et FRAGMENT sont optionnels.
Une URI simple pour notre article est :
https://ekite.tech/articles/http-anatomy
\___/ \________/ \___________________/
| | |
scheme host path
Une URI comportant des éléments supplémentaires :
https://ekite.tech/articles/http-anatomy?version=1#headers
\___/ \________/ \___________________/ \_______/ \_____/
| | | | |
scheme host path query fragment
Une URI peut également être relative, et ne comporter qu’une partie du PATH. Par exemple :
/http-anatomy?version=1#headers
Les Headers de requête
Les Headers définissent des informations supplémentaires à propos de la requête, comme le format de données attendu en réponse, ou des informations concernant les données actuellement en cache côté client.
Cette structure définit les Headers :
NAME: VALUE
La RFC 2616, définit des Headers standards, mais les applications peuvent également définir leurs propres Headers.
Les principaux Headers standards sont Accept
, Accept-Charset
, Accept-Encoding
et Accept-Language
pour la négociation de contenu.
Cette RFC définit aussi le Header Authorization
pour l’authentification des clients. Le Header Host
précise l’hôte auquel la requête est envoyée s’il n’est pas précisé dans l’URI de la requête.
Une requête HTTP comportant des Headers est :
GET /articles/http-anatomy HTTP/1.1
Host: ekite.tech
Accept: text/plain
Accept-Charset: utf-8
Accept-Encoding: gzip
Accept-Language: fr-fr
Le Body
Lorsqu’une requête comporte un corps, les Headers Content-Type
et Content-Length
doivent être précisés et définir son type et sa taille en octets.
Un saut de ligne doit également séparer les Headers du Body.
Exemple de requête avec un Body au format JSON
:
POST /articles/ HTTP/1.1
Host: ekite.tech
Content-Type: application/json
Content-Length: 31
{"title":"mon nouvel article"}
La structure d’une réponse
Les réponses HTTP ont un format assez similaire à celui des requêtes.
STATUS-LINE
[HEADERS]
[BODY]
La Status Line
La Status Line représente la réponse codifiée du serveur à la requête.
STATUS-LINE est définie de cette manière :
HTTP-VERSION CODE PHRASE
Le premier élément de la réponse est la version HTTP HTTP/1.1
Les codes utilisés sont représentés par 3 chiffres.
- Les codes
1xx
sont informationnels et rarement utilisés en pratique. - Les codes
2xx
représentent une opération en succès. - Les codes
3xx
indiquent une redirection. - Les codes
4xx
indiquent une erreur du client (requête mal formée, ressource non existante). - Les codes
5xx
représentent une erreur du serveur dans le traitement de la requête.
Les codes sont suivis d’une Phrase descriptive.
Les codes les plus courants et des phrases associées sont définis dans la RFC 2616.
Exemple de réponse en erreur :
HTTP/1.1 404 Not Found
Exemple de réponse en succès :
HTTP/1.1 200 OK
Les Headers de réponse
Au même titre qu’une requête, une réponse peut contenir des Headers. Ils définissent le type et la taille du Body de réponse, ou des paramètres pour indiquer au client que la réponse peut être stockée en cache. D’autres Headers définissent la ressource à appeler en cas de redirection (code 3xx
).
Les Headers de réponse sont définis de la même manière que les requêtes :
NAME: VALUE
Exemple de réponse HTTP comportant un Header Location
pour une redirection vers une page index.html
:
HTTP/1.1 301 Moved Permanently
Location: index.html
Le Body de réponse
Le Body est définit de la même manière que les requêtes, et impose également les mêmes règle de présence des Headers Content-Type
et Content-Length
.
Exemple de réponse en succès comportant le contenu de notre article :
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 31
{"title":"mon nouvel article"}
Exemple d’une erreur serveur, avec une page HTML la représentant :
HTTP/1.1 500 Internal Server Error
Content-Type: text/html
Content-Length: 56
<html><body><h1>Erreur de traitement</h1></body></html>
Conclusion
Le protocole HTTP décrit un format texte, sous la forme de requête et réponse, facile à implémenter dans tous les langages de programmation. Sa simplicité et son expressivité sont la clé de son succès depuis les années 90, jusqu’aux nouvelles versions qui continuent de s’appuyer sur le même format.
Références
- RFC 2616 : Hypertext Transfer Protocol – HTTP/1.1
- RFC 3986 : Uniform Resource Identifier (URI) : Generic Syntax
- RFC 7540 : Hypertext Transfer Protocol Version 2 (HTTP/2)