Le protocole HTTP¶
L’Hypertext Transfer Protocol (HTTP) est un protocole de la couche application. Il est le fondement de l’échange de données pour le World Wide Web. Comme tous les protocoles applicatifs d’Internet, HTTP est orienté texte.
HTTP version 1.1 est défini par un ensemble de RFC (Requests For Comments) maintenu par un groupe de travail de l’IETF (Internet Engineering Task Force) :
- RFC 7230 - HTTP/1.1: Message Syntax and Routing - Description de la structure des messages échangés et des procédures de connexion
- RFC 7231 - HTTP/1.1: Semantics and Content - Description des méthodes, des codes d’état et des en-têtes
- RFC 7232 - HTTP/1.1: Conditional Requests - Le support des requêtes conditionnelles
- RFC 7233 - HTTP/1.1: Range Requests - Le support de requête pour obtenir un contenu partiel
- RFC 7234 - HTTP/1.1: Caching - La gestion du cache client et des caches des éléments intermédiaires
- RFC 7235 - HTTP/1.1: Authentication - La gestion de l’authentification HTTP
Depuis 1999, le protocole HTTP était défini par la « célèbre » RFC 2616. En juin 2014, une reécriture a été publiée afin de clarifier certains points et d’améliorer la structure globale de la spécification en la scindant en six RFC distinctes.
Structure des messages¶
HTTP est un protocole sans état conversationnel dans un environnement client/serveur. Le client émet une requête qui contient les informations suffisantes pour permettre au serveur de fournir une réponse.
Une requête HTTP GET
GET /html/rfc7230 HTTP/1.1
Host: tools.ietf.org
La réponse du serveur
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 420
<html>
...
</html>
Une requête HTTP débute par une ligne de requête (request line) terminée par un saut de ligne (CRLF). Cette ligne contient la méthode HTTP que le client souhaite exécuter, le chemin de la ressource cible sur laquelle la méthode doit s’appliquer et enfin la version du protocole HTTP utilisée (HTTP/1.1).
On trouve ensuite une liste d’en-têtes et une ligne vide qui marque la fin des en-têtes. Si la requête a un contenu (un corps de message), il est ensuite transmis.
Structure d’une requête HTTP
[méthode] [ressource cible] HTTP/1.1
[Nom de l'en-tête]: [Valeur de l'en-tête]
...
[ligne vide]
[corps de message]
Lorsque le serveur reçoit la requête, il reconstitue l’URI de la requête
afin de déterminer quelle réponse il doit retourner au client. L’URI de
la requête est déterminée à partir de la ressource cible et de la valeur
de l’en-tête Host
. Ainsi pour la requête suivante :
GET /html/rfc7230 HTTP/1.1
Host: tools.ietf.org
Le serveur infère que le client veut exécuter la méthode GET
sur
l’URI :
On pourra retenir comme règle simple que le contenu de l’en-tête
Host
correspond au nom de l’hôte dans l’URI et que la ressource
cible correspond au chemin suivant l’hôte dans l’URI.
Il existe au moins trois cas particuliers pour lesquels cette rêgle ne s’applique pas :
- Si l’URI ne contient aucun chemin (par exemple https://tools.ietf.org), alors on présume que la ressource cible est /.
- La méthode
OPTIONS
autorise * comme ressource cible pour désigner le serveur dans sa globalité plutôt qu’une ressource particulière. - Pour la création d’un tunnel HTTP grâce à la méthode
CONNECT
, l’URI complète doit figurer dans la ligne de requête.
Lorsqu’on saisit une URI dans la barre d’adresse du navigateur, ce
dernier effectue le traitement inverse d’un serveur. Il transforme l’URI
en une requête HTTP valide en utilisant la méthode GET
.
Une réponse HTTP débute par une ligne de réponse (response line) terminée par un saut de ligne (CRLF). Celle-ci donne la version du protocole de réponse, le code de statut du traitement de la requête et enfin un message décrivant le code statut. On trouve ensuite une liste d’en-têtes et une ligne vide qui marque la fin des en-têtes. Si la réponse a un contenu (un corps de message), il est ensuite transmis.
Structure d’une réponse HTTP
HTTP/1.1 [code statut] [message]
[Nom de l'en-tête]: [Valeur de l'en-tête]
...
[ligne vide]
[corps de message]
En HTTP 1.1, seul l’en-tête Host est obligatoire.
Exercice¶
Écrivons en HTTP
Afficher le contenu de la page Web http://www.meteo-villes.com/ … avec telnet ! Pour rappel, le protocole HTTP est associé au port 80.
Essayez ensuite avec l’URI http://www.google.com. Quelle est la différence dans la réponse du serveur ?
Introduction à cURL
cURL est un outil en ligne de commande permettant de récupérer des données à partir d’une URL. Il supporte de nombreux protocoles dont HTTP. Vous le téléchargez à partir du site officiel.
Utilisation simple de cURL
curl https://duckduckgo.com/
cURL offre de nombreuses options. Celles qui vont nous être utiles :
- -i
- Affiche le contenu complet de la réponse HTTP. On visualise ainsi la ligne de statut et les en-têtes retournés par le serveur.
- -v
- Mode verbeux affichant notamment la requête émise et la réponse reçue.
- -X [méthode]
- Permet de préciser la méthode HTTP à utiliser dans la requête (
GET
par défaut). - -H « [en-tête] »
- Permet d’ajouter ou de modifier un en-tête de la requête.
- –data-binary [data]
- Ajoute les données spécifiées comme corps du message
- -o [nom de fichier]
- Permet de sauvegarder la réponse retournée par le serveur dans un fichier.
Utilisation avancée de cURL
curl -v -X GET -H "Accept: text/html" https://duckduckgo.com/ -o /dev/null
L’exemple ci-dessus permet d’obtenir une exécution en mode verbeux d’une
requête GET
pour l’hote duckduckgo.com pour la ressource / en ajoutant
l’en-tête Accept
avec la valeur text/html
. Le corps de la
réponse est sauvegardé dans /dev/null, c’est-à-dire nulle part, afin que
le terminal n’affiche que la ligne de statut et les en-têtes de la
réponse.
Utilisation avancée de cURL
curl -v -X POST -H "Content-type: application/json" --data-binary '{"formation": "Web Service", "année": "2018"}' http://api.web.fr/cours
L’exemple ci-dessus permet d’exécuter une méthode POST sur une API Web
hypothétique en envoyant un document JSON. cURL calculera
automatiquement pour nous la taille du message à envoyer. Il n’est donc
pas nécessaire de préciser l’en-tête Content-length
.
Reprenez les URL de l’exercice précédent pour vous familiariser avec cURL : http://www.meteo-villes.com/ et http://www.google.com.
Essayez ensuite d’utiliser la méthode HEAD puis la méthode POST plutôt que la méthode GET dans vos requêtes. Quelles différences constatez-vous ?
Les codes de statut¶
Dans la ligne de réponse, le serveur transmet le code de statut du traitement de la requête. Il s’agit d’un nombre sur 3 chiffres. Les codes de statut HTTP sont regroupés par familles identifiées par le chiffre des centaines.
- 1xx réponse informationnelle. La requête a été reçue et son traitement est en cours. Ce type de réponse n’est pas définitif : cela signifie que le client doit attendre une nouvelle réponse du serveur
- 2xx succès. La requête a été reçue avec succès, comprise et acceptée par le serveur.
- 3xx redirection. Une action supplémentaire a besoin d’être faite par le client pour terminer la requête.
- 4xx erreur du client. La requête est syntaxiquement incorrecte ou ne peut pas être prise en compte. La requête ne doit pas être émise à nouveau telle quelle.
- 5xx erreur du serveur. La serveur a échoué dans la prise en compte de la requête bien que cette dernière soit valide.
Parmi les codes existants, certains sont plus remarquables et doivent être connus :
Code | Libellé | Description |
---|---|---|
200 | OK | Le traitement de la requête est un succès et la réponse contient un message correspondant au résultat du traitement. |
201 | Created | La requête est un succès et sa prise en compte a entraîné la création d’une ou plusieurs ressources. |
204 | No Content | La requête est un succès et la réponse ne contient pas de message. |
Code | Libellé | Description |
---|---|---|
301 | Moved Permanently | Indique que le serveur connaît la ressource à laquelle le client désire
accéder mais qu’elle n’est plus disponible à l’URI spécifiée. L’en-tête
de réponse Location permet au serveur d’indiquer la nouvelle URI à
laquelle le client pourra accéder à la ressource. |
303 | See Other | La requête a été exécutée mais la réponse doit être consultée à une
autre URI. L’en-tête de réponse Location permet au serveur
d’indiquer l’URI vers laquelle le client peut exécuter un GET pour
accéder au résultat. |
307 | Temporary redirect | La requête n’a pas été traitée par le serveur et le client doit refaire
la même requête vers une URI différente. L’en-tête de réponse
Location permet au serveur d’indiquer la nouvelle URI à laquelle le
client pourra renvoyer sa requête. |
304 | Not Modified | Code d’état utilisé lors d’une requête conditionnelle pour spécifier au client que la ressource n’a pas été modifiée depuis son dernier accès. Il s’agit d’une redirection car ce code est utilisé la plupart du temps pour la gestion de la mise en cache. Le serveur notifie ainsi le client qu’il peut utiliser la représentation qu’il a déjà obtenue (et mise en cache) lors de son dernier accès. |
Code | Libellé | Description |
---|---|---|
400 | Bad Request | La requête n’a pas pu être traitée car elle est syntaxiquement incorrecte. |
404 | Not Found | Le serveur ne dispose pas de représentation pour la ressource cible. |
405 | Method Not Allowed | La ressource cible est connue du serveur mais le client ne peut pas utiliser la méthode spécifiée dans la requête. |
406 | Not Acceptable | Indique qu’il n’existe pas de représentation au format demandé par le client pour la ressource cible (échec de la négociation de contenu). |
409 | Conflict | La requête ne peut pas être traitée sans entrer en conflit avec l’état courant d’une ressource sur le serveur. |
412 | Precondition failed | Lors d’une requête conditionnelle, indique que la requête n’a pas pu être traitée car une de ses préconditions n’est pas satisfaite. |
415 | Unsupported Media Type | Indique que le message envoyé par le client utilise un format qui n’est pas supporté par le serveur. Par exemple, le client envoie au serveur un message au format XML alors que ce dernier s’attend à un document PDF. |
Code | Libellé | Description |
---|---|---|
500 | Internal Server Error | Une erreur inattendue a empêché le serveur de traiter la requête. |
Les méthodes HTTP¶
Les méthodes HTTP désignent le type d’opération que le client désire réaliser. Attention, leur nom s’écrit en majuscules dans une requête HTTP.
- GET
- Demande au serveur une représentation de la ressource cible.
- HEAD
- Comme un GET sauf que la réponse ne contient jamais de corps. Cette méthode est utile pour obtenir les informations des en-têtes et valider une requête sans envoyer ni recevoir de corps de message.
- PUT
- Crée ou met à jour l’état d’une ressource identifiée par l’URI.
- PATCH
- Change partiellement l’état d’une ressource cible. PATCH ne fait pas partie de la liste initiale des méthodes HTTP. Elle a été ajoutée en 2010 par la RFC 5789.
- DELETE
- Détruit l’association de l’URI avec l’état de la ressource.
- POST
La sémantique de la méthode POST est probablement la plus compliquée à saisir car cette méthode est utilisable dans différentes situations pour :
- Fournir un bloc de données (formulaire) à un processus de traitement
- Poster un message dans un système de centralisation d’articles
- Créer une nouvelle ressource qui sera identifiée par le serveur
- Ajouter des informations à la représentation d’une ressource
Lorsqu’un client reçoit une réponse à une méthode
POST
, il peut être important de savoir si la réponse correspond à une représentation d’une ressource ou s’il s’agit du résultat d’un traitement. Pour un code statut 200, l’en-tête de réponseContent-Location
sert à faire cette différence. S’il est présent, l’en-têteContent-Location
signale que le corps de la réponse correspond bien à la représentation d’une ressource dont l’URI est donnée par cet en-tête.- OPTIONS
- Permet d’obtenir les options de communication (par exemple : les méthodes autorisées pour l’URI). Le serveur doit retourner ces informations dans les en-têtes de réponse. Ainsi l’en-tête de réponse Allow liste les méthodes HTTP autorisées pour cette URI.
- TRACE
- Permet de simuler un écho de la requête. Cette méthode n’est pas utilisée pour la réalisation d’API Web car elle est surtout utile pour tester la configuration du réseau et obtenir des informations des proxies.
- CONNECT
- Établit un tunnel à travers un proxy. Cette méthode n’est pas utilisée pour la réalisation d’API Web.
Propriétés des méthodes HTTP¶
Les méthodes HTTP sont classées selon trois propriétés : la sûreté, l’idempotence et le support du cache (cacheable).
- Sûreté (safety)
Une méthode est sûre si le client ne s’attend à aucune modification d’état sur le serveur. Une méthode sûre est assimilable à une simple lecture de données. En tant que telle, elle doit pouvoir être exécutée entre 0 et N fois sans que cela n’affecte la ressource associée. Les méthodes GET, HEAD et OPTIONS doivent être sûres.
L’implémentation d’un serveur peut amener des modifications lors de l’exécution d’une méthode sûre. Par exemple, une requête
GET
peut générer des fichiers de log sur le serveur. Ce qu’il est important de retenir, c’est que ce type de modification n’est pas de la responsabilité du client.- Idempotence (idempotent)
Une méthode est idempotente si l’effet obtenu est le même qu’elle soit exécutée 1 ou N fois. Autrement dit, toutes choses étant égales par ailleurs, la répétition d’une requête utilisant une méthode idempotente conduit au même résultat. Les méthodes GET, HEAD, OPTIONS, PUT et DELETE doivent être idempotentes.
En HTTP, la notion d’idempotence est fortement associée à la reprise sur erreur. En effet, les requêtes utilisant des méthodes idempotentes peuvent être répétées en cas d’erreur de communication. Par exemple, si un client émet une requête
DELETE
et qu’il n’obtient pas de réponse du serveur, il peut émettre à nouveau sa requête jusqu’à obtenir une réponse. Cela fait de HTTP un protocole adapté pour des réseaux connectés mais peu fiables (Wifi, réseau data de téléphonie mobile…)
- Support du cache (cacheable)
- Une méthode cacheable indique que sa réponse peut être stockée par le client ou un proxy pour une utilisation ultérieure. Attention, il ne s’agit en rien d’une règle obligatoire et la gestion du cache en HTTP est régie par la RFC 7234. HTTP définit les méthodes GET, HEAD et POST comme étant *cacheables*. Les méthodes non cacheables forcent la suppression des données mises en cache pour l’URI lorsqu’elles sont soumises au serveur.
Sûre | Idempotente | Cacheable | |
---|---|---|---|
GET | oui | oui | oui |
HEAD | oui | oui | oui |
PUT | non | oui | non |
PATCH | non | non | non |
DELETE | non | oui | non |
POST | non | non | oui |
OPTIONS | oui | oui | non |
Les en-têtes HTTP¶
Les en-têtes de requête et de réponse permettent d’enrichir le contexte de la requête ou la réponse. Ils servent à fournir des données pour le support d’un ensemble de fonctionnalités de HTTP :
- Gestion du cycle de vie de la connexion client/serveur
- Compression du corps du message
- Gestion de la taille et du contenu des entités de requête et de réponse
- Négociation de contenu
- Requêtes conditionnelles
- Gestion des stratégies de cache
- …
Le nom des en-têtes est insensible à la casse. Les en-têtes peuvent être envoyés dans n’importe quel ordre. A titre d’exemple, on citera :
- Host (requête)
L’en-tête
Host
est le seul obligatoire en HTTP 1.1 pour un requête. Il contient le nom et le port du serveur. Sa présence permet notamment la gestion de serveurs HTTP virtuels sur un même port.Une requête HTTP avec l’en-tête
Host
GET / HTTP/1.1 Host: www.monserveur.fr:9090
- Content-Type (requête et réponse)
Si une requête ou une réponse contient un message, il est nécessaire pour le destinataire d’identifier le format du contenu. L’en-tête HTTP
Content-Type
fournit cette information sous la forme d’un type MIME.Une liste (non exhaustive) des types MIME les plus courants est :
text/plain Un fichier texte text/plain;charset=utf-8 Un fichier texte encodé en UTF-8 text/html Un fichier HTML text/xml ou application/xml Un fichier XML text/json ou application/json Un fichier JSON image/jpeg Une image au format jpeg application/x-www-form-urlencoded Le format de données pour la soumission d’un formulaire HTML application/octet-stream Un flux d’octets sans type particulier. Il s’agit du format par défaut si l’en-tête Content-type
est absent.Une requête HTTP avec l’en-tête
Content-Type
POST /utilisateur HTTP/1.1 Host: www.monserveur.fr:9090 Content-Type: application/x-www-form-urlencoded Content-Length: 36 nom=David&prenom=Gayerie&taille=174
Le IANA (Internet Assigned Numbers Authority) maintient un registre des types MIME qui lui ont été officiellement soumis.
- Content-Length (requête et réponse)
Si une requête ou une réponse contient un message, il est nécessaire pour le destinataire d’en connaître la taille afin d’identifier la fin du message HTTP. En effet le mécanisme HTTP du pipelining permet de soumettre plusieurs requêtes (et donc de recevoir plusieurs réponse) sur une même connexion TCP. La capacité de délimiter les requêtes d’une part et les réponses d’autre part est donc cruciale. L’en-tête
Content-Length
sert à communiquer la taille en octets du message.Une requête HTTP avec l’en-tête
Content-Length
POST /utilisateur HTTP/1.1 Host: www.monserveur.fr:9090 Content-Type: application/x-www-form-urlencoded Content-Length: 36 nom=David&prenom=Gayerie&taille=174
Une réponse HTTP avec l’en-tête
Content-Length
HTTP/1.1 200 OK Content-Type: text/plain; charset=utf-8 Content-Length: 17 Hello the world!
Il est possible de ne pas fournir l’en-tête
Content-Length
en utilisant la technique de l’encodage de transfert en bloc (chunked transfer encoding). Cette technique est très largement utilisée par les serveurs qui génèrent du contenu dynamique pour lequel il serait coûteux de mettre en cache la réponse avant de la transmettre pour connaître sa taille définitive.