Le protocole HTTP

Le protocole HTTP (HyperText Transfer Protocol) est un protocole de communication client-serveur.

HTTP est un protocole qui permet le transfert de données — principalement des pages web — entre un client (généralement un navigateur web) et un serveur.

Il s’agit d’un protocole sans état (→ stateless), c’est-à-dire que chaque requête est indépendante des précédentes.

Il a été créé en 1989 par Tim Berners-Lee dans le cadre du développement du World Wide Web.

Fonctionnement

Le protocole HTTP (port 80 par défaut) fonctionne selon un modèle requête-réponse :

  1. Le client envoie une requête HTTP au serveur, contenant :

    • Une méthode (GET, POST, etc.)

    • L’URL de la ressource demandée

    • La version du protocole

    • Des en-têtes avec des informations supplémentaires2

  2. Le serveur traite la requête et renvoie une réponse HTTP comprenant :

    • Un code de statut (200 OK, 404 Not Found, etc.)

    • Des en-têtes

    • Le corps de la réponse contenant les données demandées.

Versions

Le protocole a évolué au fil du temps :

  • HTTP/0.9 : Version initiale (1989)

  • HTTP/1.0 : Première version standardisée (1996)

  • HTTP/1.1 : Version la plus utilisée, introduisant des améliorations de performance (1997)

  • HTTP/2 : Version majeure apportant des optimisations significatives (2015)

  • HTTP/3 : Dernière version basée sur le protocole QUIC (en cours d’adoption).

Sécurité

La version sécurisée de HTTP, appelée HTTPS, utilise le port 443 et s’appuie sur le protocole TLS pour chiffrer les communications entre le client et le serveur.

GET vs. POST

Ce qui suit illustre le contenu des messages HTTP échangés entre un navigateur et un serveur au cours de l’utilisation d’une application web élémentaire qui se limite à un formulaire.

Cette application a été développée en Python avec le framework Flask qui utilise par défaut le port 5000 pour HTTP et non le port 80.

Cet exemple vise à montrer les différences entre une requête GET et une requête POST en terme de transmission de données :

  • GET ajoute les données de formulaire à l’URL sous forme de paramètres de requête.
    Par exemple : example.com/page?param1=value1&param2=value2

  • POST envoie les données de formulaire dans le corps de la requête HTTP, séparément de l’URL.

Ci-dessous les échanges protocolaires au niveau application HTTP (→ APDU : Application Protocol Data Unit) correspondants à la vidéo précédente :

  1. Client → Serveur : Requête GET pour accéder à la racine du site

    GET / HTTP/1.1
    Host: 127.0.0.1:5000
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:130.0) Gecko/20100101 Firefox/130.0
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8
    Accept-Language: fr,fr-FR;q=0.8,en-US;q=0.5,en;q=0.3
    Accept-Encoding: gzip, deflate, br, zstd
    Connection: keep-alive
    Upgrade-Insecure-Requests: 1
    Sec-Fetch-Dest: document
    Sec-Fetch-Mode: navigate
    Sec-Fetch-Site: none
    Sec-Fetch-User: ?1
    Priority: u=0, i
    ␍␊
    ␍␊
  2. Serveur → Client : Réponse du serveur avec la page d’accueil

    HTTP/1.1 200 OK
    Server: Werkzeug/3.0.3 Python/3.12.5
    Date: Tue, 01 Oct 2024 15:08:34 GMT
    Content-Type: text/html; charset=utf-8
    Content-Length: 736
    Connection: close
    ␍␊
    ␍␊
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Flask Forms Example</title>
    </head>
    <body>
        <h1>Exemple de formulaire</h1>
        <h2>Soumission par GET</h2>
        <form action="/submit_get" method="GET">
            <label for="nom">Nom :</label>
            <input type="text" id="nom" name="name" required>
            <button type="submit">Soumettre (GET)</button>
        </form>
        <h2>Soumission par POST</h2>
        <form action="/submit_post" method="POST">
            <label for="nom">Nom :</label>
            <input type="text" id="nom" name="name" required>
            <button type="submit">Soumettre (POST)</button>
        </form>
    </body>
    </html>
  3. Client → Serveur : Soumission du formulaire avec requête GET

    GET /submit_get?name=Ragnar HTTP/1.1 (1)
    Host: 127.0.0.1:5000
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:130.0) Gecko/20100101 Firefox/130.0
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,/;q=0.8
    Accept-Language: fr,fr-FR;q=0.8,en-US;q=0.5,en;q=0.3
    Accept-Encoding: gzip, deflate, br, zstd
    Connection: keep-alive
    Referer: http://127.0.0.1:5000/
    Upgrade-Insecure-Requests: 1
    Sec-Fetch-Dest: document
    Sec-Fetch-Mode: navigate
    Sec-Fetch-Site: same-origin
    Sec-Fetch-User: ?1
    Priority: u=0, i
    ␍␊
    ␍␊
    1 La donnée de formulaire est envoyée en tant que paramètre dans l’URL
  4. Serveur → Client : Réponse du serveur avec une page web intégrant la donnée de formulaire

    HTTP/1.1 200 OK
    Server: Werkzeug/3.0.3 Python/3.12.5
    Date: Tue, 01 Oct 2024 15:08:50 GMT
    Content-Type: text/html; charset=utf-8
    Content-Length: 332
    Connection: close
    ␍␊
    ␍␊
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Form Result</title>
    </head>
    <body>
        <h1>Résultat de la soumission de formulaire</h1>
        <p>Bonjour, Ragnar! (GET)</p> (1)
        <a href="/">Retour au formulaire</a>
    </body>
    </html>
    1 Valeur soumise via le formulaire
  5. Client → Serveur : Soumission du formulaire avec requête POST

    POST /submit_post HTTP/1.1
    Host: 127.0.0.1:5000
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:130.0) Gecko/20100101 Firefox/130.0
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,/;q=0.8
    Accept-Language: fr,fr-FR;q=0.8,en-US;q=0.5,en;q=0.3
    Accept-Encoding: gzip, deflate, br, zstd
    Content-Type: application/x-www-form-urlencoded
    Content-Length: 11
    Origin: http://127.0.0.1:5000
    Connection: keep-alive
    Referer: http://127.0.0.1:5000/
    Upgrade-Insecure-Requests: 1
    Sec-Fetch-Dest: document
    Sec-Fetch-Mode: navigate
    Sec-Fetch-Site: same-origin
    Sec-Fetch-User: ?1
    Priority: u=0, i
    ␍␊
    ␍␊
    name=Ragnar(1)
    1 la donnée de formulaire est transmise dans la requête, à la suite de l’entête
  6. Serveur → Client : Réponse du serveur avec page web intégrant la donnée de formulaire

    HTTP/1.1 200 OK
    Server: Werkzeug/3.0.3 Python/3.12.5
    Date: Tue, 01 Oct 2024 15:08:56 GMT
    Content-Type: text/html; charset=utf-8
    Content-Length: 333
    Connection: close
    ␍␊
    ␍␊
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Form Result</title>
    </head>
    <body>
        <h1>Résultat de la soumission de formulaire</h1>
        <p>Bonjour, Ragnar! (POST)</p> (1)
        <a href="/">Retour au formulaire</a>
    </body>
    </html>
    1 Valeur soumise via le formulaire

🞄  🞄  🞄