Aller au contenu principal

Rappel sur le protocole HTTP

HyperText Transfer Protocol

Cycle Requête/Réponse HTTP


Notions théoriques

Qu'est-ce que HTTP ?

HTTP (HyperText Transfer Protocol) est le protocole de communication utilisé sur le Web pour échanger des données entre un client (le navigateur) et un serveur (le serveur Web).

info

HTTP est un protocole de la couche application. Il repose sur TCP/IP et utilise par défaut :

  • Port 80 pour HTTP
  • Port 443 pour HTTPS (HTTP sécurisé avec TLS/SSL)

Le cycle Requête/Réponse

HTTP fonctionne sur un modèle fondamental : le client envoie une requête, le serveur renvoie une réponse.

Client (navigateur) Serveur Web
| |
| ------- Requête HTTP ----> |
| | (traitement)
| <------ Réponse HTTP ----- |
| |
remarque

La communication HTTP est toujours initiée par le client. Le serveur ne peut pas envoyer de données spontanément sans avoir reçu une requête au préalable (sauf avec des technologies complémentaires comme WebSockets ou Server-Sent Events).


Structure d'une requête HTTP

Une requête HTTP se compose de trois parties :

  1. La ligne de requête — méthode + URL + version HTTP
  2. Les en-têtes (headers) — informations sur le client, le format attendu, etc.
  3. Le corps (body) — données envoyées au serveur (uniquement pour POST, PUT, PATCH)

Exemple de requête GET (sans corps) :

GET /articles/42 HTTP/1.1
Host: www.exemple.fr
Accept: text/html
User-Agent: Mozilla/5.0

Exemple de requête POST (avec corps) :

POST /articles HTTP/1.1
Host: www.exemple.fr
Content-Type: application/json
Content-Length: 45

{"titre": "Mon article", "contenu": "Bonjour !"}

Les méthodes HTTP (verbes)

Les méthodes indiquent l'action que le client souhaite effectuer sur la ressource :

MéthodeActionCorps ?Idempotent ?
GETRécupérer une ressourceNonOui
POSTCréer une ressourceOuiNon
PUTRemplacer une ressource entièreOuiOui
PATCHModifier partiellement une ressourceOuiNon
DELETESupprimer une ressourceNonOui
astuce

Dans une application Symfony, vous associerez des routes à des méthodes HTTP précises. Par exemple, GET /articles liste les articles et POST /articles en crée un nouveau — même URL, action différente selon la méthode.


Structure d'une réponse HTTP

Une réponse HTTP contient :

  1. La ligne de statut — version HTTP + code de statut + message
  2. Les en-têtes (headers) — type de contenu retourné, cookies, cache, etc.
  3. Le corps (body) — HTML, JSON, image, etc.

Exemple de réponse :

HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
Content-Length: 1234

<!DOCTYPE html>
<html lang="fr">
<body><h1>Mon article</h1></body>
</html>

Les codes de statut HTTP les plus courants :

CodeMessageSignification
200OKSuccès
201CreatedRessource créée avec succès
301Moved PermanentlyRedirection permanente
302FoundRedirection temporaire
400Bad RequestRequête invalide (données manquantes ou incorrectes)
401UnauthorizedAuthentification requise
403ForbiddenAccès refusé (authentifié mais non autorisé)
404Not FoundRessource introuvable
422Unprocessable EntityDonnées invalides (formulaire)
500Internal Server ErrorErreur côté serveur
attention

Ne pas confondre 401 et 403 :

  • 401 : l'utilisateur n'est pas identifié (il doit se connecter)
  • 403 : l'utilisateur est identifié mais n'a pas les droits nécessaires

HTTP est un protocole sans état (stateless)

attention

HTTP est stateless : chaque requête est totalement indépendante des précédentes. Le serveur ne conserve aucune mémoire des échanges passés avec un client.

Concrètement, si un utilisateur envoie deux requêtes successives :

Requête 1 : POST /login → le serveur vérifie login + mot de passe
Requête 2 : GET /dashboard → le serveur ne sait pas qui demande !

Pour le serveur, chaque requête repart de zéro. Il n'y a pas de lien automatique entre elles.

Conséquences du stateless

  • Il est impossible de maintenir un utilisateur "connecté" nativement avec HTTP seul
  • Chaque requête doit transporter par elle-même toutes les informations nécessaires au traitement
  • En contrepartie, le serveur peut traiter les requêtes en parallèle et en charge (scalabilité horizontale)
astuce

Le stateless est un avantage architectural : n'importe quel serveur d'un cluster peut traiter n'importe quelle requête sans avoir besoin d'état partagé.


Compenser le stateless : cookies et sessions

Pour simuler un "état" malgré le stateless d'HTTP, deux mécanismes complémentaires existent :

Les cookies

Un cookie est une petite donnée stockée côté client par le navigateur. Le serveur l'envoie dans une réponse via l'en-tête Set-Cookie, et le navigateur le renvoie automatiquement dans les requêtes suivantes vers le même domaine.

# Le serveur envoie un cookie dans la réponse :
HTTP/1.1 200 OK
Set-Cookie: theme=dark; Path=/; HttpOnly; Secure

# Le navigateur le renvoie automatiquement dans les requêtes suivantes :
GET /page HTTP/1.1
Cookie: theme=dark

Les sessions

Une session stocke les données côté serveur. Le client reçoit uniquement un identifiant de session (généralement dans un cookie), et le serveur retrouve les données associées à cet identifiant à chaque requête.

Requête 1 — Connexion :
Client --> POST /login (identifiants)
Serveur --> crée une session #abc123, stocke l'utilisateur
Serveur --> Set-Cookie: PHPSESSID=abc123

Requête 2 — Tableau de bord :
Client --> GET /dashboard + Cookie: PHPSESSID=abc123
Serveur --> retrouve la session #abc123, identifie l'utilisateur
Serveur --> 200 OK avec les données de l'utilisateur
info

Les cookies et les sessions ne font pas partie du protocole HTTP de base — ce sont des conventions implémentées par les navigateurs et les frameworks. En Symfony, la gestion des sessions est assurée par le composant HttpFoundation.


HTTP en Symfony : Request et Response

Symfony modélise le cycle HTTP avec deux classes du composant HttpFoundation :

  • Request — encapsule la requête entrante (méthode, URL, paramètres, en-têtes, cookies, session)
  • Response — encapsule la réponse à envoyer (code de statut, en-têtes, corps)
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Attribute\Route;

class ArticleController extends AbstractController
{
#[Route('/articles', methods: ['GET'])]
public function index(Request $request): Response
{
$page = $request->query->get('page', 1); // paramètre GET ?page=1

return new Response('<h1>Liste des articles — page ' . $page . '</h1>');
}

#[Route('/articles', methods: ['POST'])]
public function create(Request $request): Response
{
$titre = $request->request->get('titre'); // paramètre POST

// Traitement...

return new Response('Article créé : ' . $titre, Response::HTTP_CREATED); // 201
}
}
remarque

Dans un contrôleur Symfony, l'objet Request est injecté automatiquement s'il est déclaré en paramètre. Chaque action retourne obligatoirement un objet Response (ou une sous-classe : JsonResponse, RedirectResponse, etc.).


Exemple pratique

Voici un échange HTTP complet lors de la consultation d'un article sur une application Symfony.

1. Le navigateur envoie une requête GET :

GET /articles/42 HTTP/1.1
Host: localhost:8000
Accept: text/html,application/xhtml+xml
Accept-Language: fr-FR,fr;q=0.9
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
Cookie: PHPSESSID=abc123xyz

2. Symfony traite la requête dans le contrôleur :

#[Route('/articles/{id}', methods: ['GET'])]
public function show(int $id, Request $request): Response
{
// $id = 42, extrait depuis l'URL par le routeur Symfony
$article = $this->articleRepository->find($id);

if (!$article) {
throw $this->createNotFoundException('Article introuvable'); // → 404
}

return $this->render('article/show.html.twig', [
'article' => $article,
]); // → 200 + HTML généré par Twig
}

3. Le serveur renvoie la réponse :

HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
Cache-Control: no-cache, private
X-Debug-Token: d4a2e1

<!DOCTYPE html>
<html lang="fr">
<head><title>Article #42 — Mon Blog</title></head>
<body>
<h1>Mon premier article</h1>
<p>Contenu de l'article...</p>
</body>
</html>
astuce

Observez ces échanges dans les DevTools de votre navigateur (F12 → onglet Réseau / Network). Chaque ligne représente une requête HTTP : vous y verrez la méthode, l'URL, le code de statut et les en-têtes complets.


Test de mémorisation/compréhension


Quel acteur initie toujours la communication en HTTP ?


Qu'est-ce que signifie 'HTTP est stateless' ?


Quelle méthode HTTP utilise-t-on pour créer une nouvelle ressource ?


Quel code de statut HTTP indique qu'une ressource n'a pas été trouvée ?


Comment le serveur reconnaît-il un utilisateur d'une requête à l'autre malgré le stateless d'HTTP ?


Dans Symfony, quelle classe représente la requête HTTP entrante ?


Quelle est la différence entre le code 401 et le code 403 ?


Quelle propriété de l'objet Request Symfony permet d'accéder aux paramètres de l'URL (?page=2) ?



TP pour réfléchir et résoudre des problèmes

Observer et analyser le protocole HTTP

Dans ce TP, vous allez observer des échanges HTTP réels et créer un contrôleur Symfony qui respecte les conventions HTTP.


Étape 1 — Observer les requêtes HTTP dans le navigateur

Ouvrez n'importe quel site Web (par exemple votre application Symfony locale), puis ouvrez les DevTools (F12) et allez dans l'onglet Réseau (Network).

Rechargez la page et observez :

  • La liste des requêtes HTTP
  • La méthode (GET, POST...) et l'URL de chaque requête
  • Le code de statut de la réponse
  • Les en-têtes envoyés et reçus
astuce

Cliquez sur une requête pour voir ses détails. Repérez les onglets Headers (en-têtes), Response (corps de la réponse) et Cookies.


Étape 2 — Identifier les codes de statut

En observant l'onglet Réseau, retrouvez un exemple de chacun de ces codes dans votre navigation quotidienne :


Étape 3 — Créer un contrôleur Symfony qui répond aux méthodes GET et POST

Dans votre projet Symfony, créez un contrôleur MessageController avec deux actions :

  • GET /messages : retourne une liste de messages en JSON
  • POST /messages : crée un message et retourne une réponse 201

Étape 4 — Lire un paramètre POST dans Symfony

Complétez l'action create pour récupérer le champ contenu envoyé dans le corps de la requête POST.


Étape 5 — Tester avec curl

Testez vos deux routes depuis un terminal avec la commande curl :

# Tester GET /messages
curl -X GET http://localhost:8000/messages

# Tester POST /messages avec un paramètre
curl -X POST http://localhost:8000/messages \
-d "contenu=Bonjour le monde"
attention

Si vous obtenez une erreur 405 Method Not Allowed, vérifiez que l'attribut methods de votre route correspond bien à la méthode HTTP utilisée dans la requête.


Une solution complète — MessageController