Les bases de HTTP
- Leçon 2
- 35 min
- Module 1 : Comprendre la requête Web
Leçon 2 sur 21 · Créer et déployer votre première APILes bases de HTTP
1. Comprendre la requête Web
2. Créer un petit service FastAPI
3. Concevoir un contrat utilisable
4. Documenter l'API avec OpenAPI et Swagger UI
5. Explorer et tester avec Postman
6. Tester et renforcer le service
7. Déployer et vérifier
Ce que vous saurez faire
Lisez toute requête et réponse HTTP, partie par partie. Choisissez la bonne méthode et le bon code d’état pour votre API. Chaque point de terminaison que vous créez dans ce cours repose sur un choix de ces parties.
Avant de commencerCe qu’il faut savoir et avoir sous la main
Ce que vous devez savoir
- Les étapes de Du navigateur au serveur : les bases : le trajet complet : DNS, connexion, TLS, puis HTTP.
Ce qu’il vous faut sur votre ordinateur
- Un terminal avec un environnement virtuel Python contenant httpx 0.28.1. Par exemple, votre projet
ticket-cleaner, configuré dans Isoler les dépendances : exercices guidés : configurer ticket-cleaner. Si vous n’en avez pas, créez-en un dans un nouveau dossier :python3 -m venv .venv. Activez-le, puis exécutezpython -m pip install httpx==0.28.1. - Une connexion Internet. Les exemples utilisent Postman Echo, un service public gratuit de Postman qui vous renvoie votre requête. Aucun compte n’est nécessaire.
Testé avec Python 3.14.6 et httpx 0.28.1 sur macOS.
Une requête, partie par partie
Section intitulée « Une requête, partie par partie »Voici la requête que vous enverrez à votre API plus tard dans le cours. Elle est présentée en texte, exactement comme HTTP l’envoie :
POST /v1/classify?lang=en HTTP/1.1Host: api.example.comContent-Type: application/jsonAccept: application/jsonX-API-Key: k-7f3a9c
{"subject": "Charged twice for March", "body": "Same invoice two times."}| Partie | Dans l’exemple | Signification |
|---|---|---|
| Méthode | POST |
Ce que le client veut faire. |
| Chemin et paramètres de requête | /v1/classify?lang=en |
La ressource visée, avec des valeurs supplémentaires. |
| En-têtes | Content-Type: application/json et les lignes suivantes |
Des renseignements sur la requête, sous forme de lignes Name: value (nom : valeur). |
| Ligne vide | Marque la fin des en-têtes. | |
| Corps | Le texte JSON | Les données que le client envoie. Facultatif. |
Méthodes
Section intitulée « Méthodes »La méthode indique ce que le client veut faire avec la ressource. Les API en utilisent surtout cinq :
| Méthode | Signification | Corps? | Exemple |
|---|---|---|---|
GET |
Lire une ressource. Ne rien changer. | Non | GET /v1/categories |
POST |
Envoyer des données à traiter ou créer une ressource. | Oui | POST /v1/classify |
PUT |
Remplacer complètement une ressource. | Oui | PUT /v1/tickets/T-1001 |
PATCH |
Modifier une partie d’une ressource. | Oui | PATCH /v1/tickets/T-1001 |
DELETE |
Supprimer une ressource. | Non | DELETE /v1/tickets/T-1001 |
GET est sûre : elle ne change jamais rien sur le serveur. Un client, un navigateur ou un cache peut donc la répéter sans risque. C’est pourquoi une requête qui modifie des données ne doit jamais utiliser GET. Un navigateur peut charger un lien GET avant que vous cliquiez dessus. Ce lien ne doit rien supprimer.
Une API organisée autour de ressources et de ces méthodes s’appelle une API REST. Les ressources sont des éléments avec une adresse, comme /v1/tickets/T-1001. La plupart des API Web suivent ce style, tout comme l’API de ce cours.
Paramètres de chemin et paramètres de requête
Section intitulée « Paramètres de chemin et paramètres de requête »Une valeur dans l’URL peut se trouver dans le chemin ou dans les paramètres de requête. Ces deux emplacements ont des rôles différents :
| Type | Exemple | Utilisation |
|---|---|---|
| Paramètre de chemin | /v1/tickets/T-1001 |
Indiquer la ressource visée. Sans ce paramètre, l’URL désigne autre chose. |
| Paramètre de requête | /v1/tickets?status=open&limit=20 |
Préciser des options : filtres, ordre de tri, taille de page. On peut généralement les omettre. |
Toutes les valeurs d’une URL sont du texte. Le serveur convertit limit=20 en nombre 20. Il doit rejeter limit=twenty avec une erreur claire, comme vous l’avez fait pour les données de fichiers dans le cours Python.
En-têtes
Section intitulée « En-têtes »Les en-têtes transmettent des renseignements sur la requête ou la réponse. Leur nom ne distingue pas les majuscules des minuscules : content-type et Content-Type désignent le même en-tête. Voici les en-têtes courants dans ce cours :
| En-tête | Envoyé par | Signification |
|---|---|---|
Content-Type |
Les deux | Le format du corps, par exemple application/json. |
Accept |
Client | Les formats que le client peut lire. |
X-API-Key ou Authorization |
Client | Prouve l’identité de l’appelant. Le module 6 ajoute une clé d’API. |
X-Request-ID |
Serveur | Un identifiant de cette requête, pour la retrouver dans les journaux (logs). Le module 6 l’ajoute. |
Content-Length |
Les deux | La taille du corps en octets. |
Les en-têtes qui commencent par X- ne font pas partie de la norme HTTP. Les applications les définissent pour leurs propres besoins.
Corps et JSON
Section intitulée « Corps et JSON »Un corps peut contenir n’importe quelles données, mais les API utilisent presque toujours JSON (JavaScript Object Notation). JSON est du texte contenant des objets, des listes, des chaînes, des nombres, true (vrai), false (faux) et null (nul). Vous l’avez utilisé dans le cours Python. L’en-tête Content-Type: application/json indique à l’autre côté comment lire le corps. Sans lui, plusieurs serveurs rejettent le corps ou le lisent comme du texte brut.
Exemple détaillé : voir ce que le serveur reçoit
Section intitulée « Exemple détaillé : voir ce que le serveur reçoit »Amira utilise Postman Echo, qui répond avec une copie de ce qu’il a reçu. Elle démarre Python en mode interactif dans son environnement virtuel (python). Elle envoie ensuite une requête GET avec deux paramètres de requête :
>>> import httpx>>> r = httpx.get("https://postman-echo.com/get", params={"status": "open", "limit": 2}, timeout=10)>>> r.request.urlURL('https://postman-echo.com/get?status=open&limit=2')>>> r.status_code, r.headers["content-type"](200, 'application/json; charset=utf-8')>>> r.json()["args"]{'status': 'open', 'limit': '2'}httpx a construit les paramètres de requête à partir du dictionnaire : ?status=open&limit=2. Le serveur a reçu limit comme texte '2', et non comme nombre 2. Toutes les valeurs d’une URL sont du texte.
Elle envoie ensuite une requête POST avec un corps JSON :
>>> r = httpx.post("https://postman-echo.com/post", json={"subject": "Charged twice", "priority": 1}, timeout=10)>>> r.request.headers["content-type"]'application/json'>>> r.request.contentb'{"subject":"Charged twice","priority":1}'>>> r.json()["json"]{'subject': 'Charged twice', 'priority': 1}L’argument json= a fait deux choses. Il a converti le dictionnaire en texte JSON pour le corps et ajouté l’en-tête Content-Type: application/json. Dans le corps, priority reste un nombre, car JSON prend en charge les nombres.
Codes d’état
Section intitulée « Codes d’état »Le code d’état indique le résultat au client. Vous avez vu les groupes dans le cours Python : 2xx pour un succès, 4xx pour un problème avec la requête. Le groupe 5xx indique un problème sur le serveur. Une API doit choisir le code le plus précis, car les programmes agissent en fonction de ce code :
| Code | Nom | Quand l’utiliser |
|---|---|---|
200 |
OK (succès) | La requête a réussi et le corps contient le résultat. |
201 |
Created (créé) | Une requête POST a créé une ressource. |
204 |
No Content (aucun contenu) | L’opération a réussi et il n’y a rien à renvoyer. |
400 |
Bad Request (requête incorrecte) | La requête est incorrecte de façon générale. |
401 |
Unauthorized (non authentifié) | Aucune information d’authentification valide, par exemple une clé d’API manquante. |
403 |
Forbidden (interdit) | Les informations d’authentification sont valides, mais l’action n’est pas permise. |
404 |
Not Found (introuvable) | Aucune ressource à ce chemin. |
413 |
Content Too Large (contenu trop volumineux) | Le corps dépasse la taille acceptée par le serveur. |
422 |
Unprocessable Content (contenu impossible à traiter) | Le JSON est lisible, mais une valeur n’est pas valide. FastAPI l’utilise pour les erreurs de validation. |
429 |
Too Many Requests (trop de requêtes) | Le client a envoyé trop de requêtes. Attendez, puis réessayez. |
500 |
Internal Server Error (erreur interne du serveur) | Le serveur a rencontré une erreur inattendue : un bogue. |
503 |
Service Unavailable (service indisponible) | Le serveur, ou un composant nécessaire, est indisponible pour le moment. Réessayez plus tard. |
La différence entre 4xx et 5xx détermine ce que le client fait ensuite. Après un 4xx, le client doit modifier la requête : la renvoyer ne sert à rien. Après un 503, la même requête peut réussir plus tard.
Exercice guidé : lire les parties
Section intitulée « Exercice guidé : lire les parties »-
Démarrez Python en mode interactif dans un environnement virtuel contenant httpx.
-
Envoyez une requête
GETàhttps://postman-echo.com/getavec les paramètres de requêtecategory=billingetpage=3. Affichezr.request.urletr.json()["args"].Vous voyez
?category=billing&page=3dans l’URL, et les deux valeurs sous forme de texte. -
Envoyez une requête
POSTàhttps://postman-echo.com/postavec le corps JSON{"subject": "Locked out", "urgent": true}. Affichezr.json()["json"].Le corps revient avec
'urgent': True: letruede JSON est devenuTrueen Python. -
Envoyez une requête qui reçoit le code d’état de votre choix. Postman Echo répond à
https://postman-echo.com/status/404avec le code404. Affichezr.status_code, puis essayez201et503.
À vous de jouer : concevoir trois requêtes
Section intitulée « À vous de jouer : concevoir trois requêtes »Le service de soutien veut trois fonctionnalités de plus. Pour chacune, écrivez la méthode, le chemin, les paramètres de requête éventuels et le code d’état en cas de succès. Précisez aussi s’il y a un corps. Utilisez /v1/tickets comme chemin de base.
- Obtenir les billets de soutien ouverts, 20 à la fois.
- Changer seulement l’état du billet
T-1042pourclosed(fermé). - Supprimer le billet
T-1042. Après cela, que renvoie une requêteGETpour ce même billet?
Afficher une réponse possible
GET /v1/tickets?status=open&limit=20. Aucun corps.200, avec une liste dans le corps. Le filtre et la taille de page sont des options, donc des paramètres de requête.PATCH /v1/tickets/T-1042, avec le corps{"status": "closed"}.200avec le billet modifié, ou204sans corps. L’identifiant est dans le chemin, car il indique la ressource visée.DELETE /v1/tickets/T-1042. Aucun corps.204. Une requête ultérieureGET /v1/tickets/T-1042renvoie404, car la ressource n’existe plus.
Erreur courante
Le serveur ignore le corps JSON
Symptôme : vous envoyez du JSON correct, mais le serveur répond 422 et indique que le corps n’est pas valide. L’API de ce cours répond "fields": ["body"] (champs : corps). Certains services, comme Postman Echo, devinent le format. La même requête peut donc y réussir et échouer sur votre API.
Cause : la requête n’a pas d’en-tête Content-Type: application/json. Le serveur ne sait donc pas que le corps est du JSON. Cela arrive quand vous écrivez vous-même le corps en texte, par exemple httpx.post(url, content='{"subject": "x"}'). Cela arrive aussi dans curl sans option -H.
Solution :
- Dans httpx, utilisez
json=avec un dictionnaire. Il définit l’en-tête pour vous. - Si vous envoyez le corps en texte, ajoutez vous-même l’en-tête :
headers={"Content-Type": "application/json"}. - Vérifiez la requête réellement envoyée :
r.request.headers.
Vérifiez votre compréhension
Un point de terminaison GET /v1/tickets/delete?id=T-1042 supprime un billet. Quel est le problème avec cette conception?
Afficher la réponse
Il utilise GET pour modifier des données. GET doit être sûre : les navigateurs, les aperçus de liens et les caches envoient des requêtes GET sans consulter l’utilisateur. Chacune de ces requêtes supprimerait un billet. Utilisez DELETE /v1/tickets/T-1042. C’est la méthode qui indique l’action, pas un mot dans le chemin.
Votre réponse contient-elle les points principaux de la nôtre ?
Connectez-vous et inscrivez-vous au cours pour enregistrer vos réponses. Chaque vérification compte pour le certificat.
Vérifiez votre compréhension
Votre API ne peut pas joindre le classificateur dont elle dépend. Quel code d'état doit-elle renvoyer : 400, 404, 500 ou 503? Pourquoi?
Afficher la réponse
503 Service Unavailable (service indisponible). La requête est correcte (ni 400 ni 404), et le serveur n’a pas de bogue (pas 500). Un composant nécessaire au service est indisponible pour le moment, et la même requête peut réussir plus tard. Un client peut réessayer sans risque après une courte attente.
Votre réponse contient-elle les points principaux de la nôtre ?
Connectez-vous et inscrivez-vous au cours pour enregistrer vos réponses. Chaque vérification compte pour le certificat.
Récapitulatif
- Une requête comprend une méthode, un chemin avec des paramètres de requête facultatifs, des en-têtes et un corps facultatif. Une réponse comprend un code d’état, des en-têtes et un corps.
GETlit et est sûre.POST,PUT,PATCHetDELETEmodifient des données.- Un paramètre de chemin indique la ressource visée. Un paramètre de requête donne une option. Toutes les valeurs d’une URL sont du texte.
Content-Type: application/jsonindique à l’autre côté que le corps est du JSON.- Choisissez le code d’état le plus précis.
4xx: modifiez la requête.5xx: le problème est sur le serveur.
Ensuite, vous examinerez de vraies requêtes avec les outils de développement de votre navigateur et avec curl.
Leçon suivante : Examiner une requête