Rappel sur le protocole HTTP
HyperText Transfer Protocol

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).
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 ----- |
| |
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 :
- La ligne de requête — méthode + URL + version HTTP
- Les en-têtes (headers) — informations sur le client, le format attendu, etc.
- 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éthode | Action | Corps ? | Idempotent ? |
|---|---|---|---|
GET | Récupérer une ressource | Non | Oui |
POST | Créer une ressource | Oui | Non |
PUT | Remplacer une ressource entière | Oui | Oui |
PATCH | Modifier partiellement une ressource | Oui | Non |
DELETE | Supprimer une ressource | Non | Oui |
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 :
- La ligne de statut — version HTTP + code de statut + message
- Les en-têtes (headers) — type de contenu retourné, cookies, cache, etc.
- 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 :
| Code | Message | Signification |
|---|---|---|
200 | OK | Succès |
201 | Created | Ressource créée avec succès |
301 | Moved Permanently | Redirection permanente |
302 | Found | Redirection temporaire |
400 | Bad Request | Requête invalide (données manquantes ou incorrectes) |
401 | Unauthorized | Authentification requise |
403 | Forbidden | Accès refusé (authentifié mais non autorisé) |
404 | Not Found | Ressource introuvable |
422 | Unprocessable Entity | Données invalides (formulaire) |
500 | Internal Server Error | Erreur côté serveur |
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)
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)
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
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
}
}
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>
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
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
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 JSONPOST /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"
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
Vous devez être connecté pour voir le contenu.