Le protocole HTTP

Requêtes et réponses HTTP

Une requête HTTP est un flux d’octets (un texte) envoyé par le client vers le serveur au travers du réseau. Elle est structurée en lignes.

Exemple d’une requête de type GET :

$ curl -v https://yesno.wtf/api 
* ...
> GET /api HTTP/1.1
> Host: yesno.wtf
> User-Agent: curl/8.1.2
> Accept: */*
> 
< HTTP/1.1 200 OK
< Content-Type: application/json; charset=utf-8
< Transfer-Encoding: chunked
< Connection: keep-alive
< Status: 200 OK
< Cache-Control: max-age=0, private, must-revalidate
< Access-Control-Allow-Origin: *
< X-XSS-Protection: 1; mode=block
< X-Request-Id: d827740d-2573-40bf-88c5-33ac52d650a4
< ETag: "d3527d4290696162cc5d62dec55d8cf6"
< X-Frame-Options: SAMEORIGIN
< X-Runtime: 0.002412
< X-Content-Type-Options: nosniff
< Access-Control-Request-Method: *
< Date: Tue, 21 Nov 2023 05:07:26 GMT
< X-Powered-By: Phusion Passenger 6.0.4
< Server: nginx/1.17.3 + Phusion Passenger 6.0.4
< 
{"answer":"yes","forced":false,"image":"https://yesno.wtf/assets/yes/3-422e51268d64d78241720a7de52fe121.gif"}
La requête (request) est le texte formé des lignes suivantes :
GET /api HTTP/1.1
Host: yesno.wtf
User-Agent: curl/8.1.2
Accept: */*

La réponse (response) est le texte formé des lignes suivantes :

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
Status: 200 OK
Cache-Control: max-age=0, private, must-revalidate
Access-Control-Allow-Origin: *
X-XSS-Protection: 1; mode=block
X-Request-Id: d827740d-2573-40bf-88c5-33ac52d650a4
ETag: "d3527d4290696162cc5d62dec55d8cf6"
X-Frame-Options: SAMEORIGIN
X-Runtime: 0.002412
X-Content-Type-Options: nosniff
Access-Control-Request-Method: *
Date: Tue, 21 Nov 2023 05:07:26 GMT
X-Powered-By: Phusion Passenger 6.0.4
Server: nginx/1.17.3 + Phusion Passenger 6.0.4

{"answer":"yes","forced":false,"image":"https://yesno.wtf/assets/yes/3-422e51268d64d78241720a7de52fe121.gif"}

Les requêtes sont souvent envoyées par les navigateurs web :

  • obtention du contenu d’une page
  • obtention du contenu d’un fichier de script (js) ou de style (css)
  • post des données d’un formulaire
  • appel d’un webservice, sur le serveur d’origine ou sur un autre serveur (cross-origin)

Elles peuvent aussi être envoyées par tout type de programme ou d’application.

Par exemple, la commande GNU curl permet facilement d’envoyer des requêtes à un serveur et d’en afficher la réponse :

$ curl -X GET -H "Content-Type: application/json" -H "Accept: application/json"
-H "Authorization: Bearer eyJhbGci..." -d '{"type":"patient"}' https://xxx.yyy.dev/api/v1/users

Principaux headers

Headers de la requête

Content-type

Type du média du body de la requête

Content-Type: application/json
Content-Type: text/html

Accept

Indique quels sont les types de contenu, exprimés sous la forme de types MIME, que le client sera capable d’interpréter

Headers de la réponse

Content-type

Type du média du body de la réponse

Content-Type: application/json
Content-Type: text/html

ETag / If-None-Match

Etag (Entity Tag) = Identifiant unique de la ressource demandée, renvoyé par le serveur.

Si le navigateur demande la même ressource et qu’il ajoute le header If-None-Match: "valeur-du-etag", le serveur peut vérifier si la ressource a changé. Si elle n’a pas changé, il renvoie 304 - not modified

Le header ETag est prioritaire sur le header Cache-Control

Cache-Control

Indique au navigateur de ne pas chercher à charger une version plus récente d’une ressource avant une certaine date.

Cache-Control: "no-cache, no-store, max-age=0, must-revalidate"

Cookies

Un cookie est une paire (clé, valeur) qui est stockée dans un espace dédié du navigateur, associé au nom de domaine appelé.

Un serveur peut mettre dans une response HTTP un ordre de stockage d’un nouveau cookie dans le navigateur client :

Set-Cookie: token=JjlmIyAZuV6u6HY4R8Vl8byOhvkkLzZDTcgTD7Paehe3xLy4VI; mode=dev;

Lors de chaque requête sur le même nom de domaine, le navigateur inclue systématiquement tous les cookies dans la requête HTTP, dans une ligne (attention à l’espace après ;) :

Cookie: key1=value1; key2=value2;

Exemple:

GET /spec.html HTTP/1.1
Host: www.example.org
Cookie: token=JjlmIyAZuV6u6HY4R8Vl8byOhvkkLzZDTcgTD7Paehe3xLy4VI; mode=dev; 
--cookie "key=value"

Fonctions et librairies de requêtes HTTP

NodeJS (back-end) & Javascript (front-end)

Plusieurs librairies existent, basées sur le package http.

Exemple avec la librairie axios :

const response = await axios({
   url: USERS_ENDPOINT,
   method: 'post',
   headers: {
      "Authorization": `Bearer ${sessionToken}`,
      "Content-Type": "application/json",
   },
   data: userData,
})
const createdUser = response.data
...

Javascript (front-end)

Les requêtes http effectuées depuis un script par le navigateur sont appelées requêtes XHR (XML HTTP Request). On les effectue avec la fonction built-in fetch.

Exemple :

const response = await fetch(USERS_ENDPOINT, {
   method: 'POST',
   headers: {
      "Content-Type": "application/json",
   },
   body: userData,
})
const createdUser = await response.json()