# Le backend et HTTP : qui fait quoi, les méthodes et les codes d'état<no value>

## Dans cette leçon

Cette leçon se compose de deux chapitres, dans le même ordre que les diapositives :

1. **Chapitre 1** — ce qu'est un backend : client, serveur, base de données, API et endpoint
2. **Chapitre 2** — les méthodes HTTP et les codes d'état

## Chapitre 1 : Ce qu'est un backend — client, serveur, base de données, API et endpoint

### Qu'allons-nous apprendre ?

Nous passons maintenant de programmes qui tournent **sur notre propre ordinateur** à des logiciels auxquels **d'autres** s'adressent par le réseau. Cette leçon donne la vue d'ensemble et le vocabulaire :

- **Le backend** et **le frontend**.
- **Le client**, **le serveur** et **la base de données** : comment ils travaillent ensemble.
- **L'API** et **l'endpoint**.

### Pourquoi en avons-nous besoin ?

Chaque application que vous connaissez (Wolt, Instagram, le site de la banque) est construite en deux parties : ce que vous voyez (le frontend), et ce qui se passe « en coulisses » (le backend) : enregistrer les données, vérifier les permissions, calculer les prix. Les développeurs Full Stack écrivent les deux. Les développeurs Data travaillent tous les jours avec des API et des bases de données.

À la fin de ces thèmes, vous construirez un vrai backend : un serveur qui reçoit des requêtes d'Internet, enregistre dans une base de données, et renvoie des réponses.

### Explication à partir des bases

#### Frontend face à backend

| | Frontend | Backend |
|---|---|---|
| Ce que c'est | La partie que **l'utilisateur voit** et utilise | La partie qui tourne **sur le serveur**, en coulisses |
| Où il tourne | Dans le navigateur / dans l'application du téléphone | Sur un ordinateur serveur (dans le cloud / dans l'entreprise) |
| Rôle | Affichage, formulaires, boutons | Logique métier, enregistrement des données, sécurité |
| Exemple dans une boutique | La page produit, le bouton « ajouter au panier » | Vérifier le stock, calculer le prix, enregistrer la commande |
| Technologies | HTML, CSS, JavaScript, React | **Python + FastAPI**, Node.js, Java... |

{{< box "analogy" "Analogie : un restaurant" >}}
**Frontend** = la salle du restaurant : le menu, les tables, le serveur qui prend la commande. **Backend** = la cuisine : c'est là que la nourriture est vraiment préparée, qu'on vérifie qu'il y a des ingrédients et qu'on respecte les règles (pas de viande avec du lait dans une cuisine casher). **Base de données** = la réserve et le réfrigérateur : c'est là que tout le stock est conservé. Le client n'entre jamais dans la cuisine ni dans la réserve. Il ne parle qu'au serveur.
{{< /box >}}

#### Client, serveur, base de données — les trois acteurs

Vous vous souvenez du thème sur l'ordinateur, le système d'exploitation et le réseau ? Le client prend l'initiative, le serveur répond. Nous ajoutons maintenant un troisième acteur :

```text
  ┌──────────┐   HTTP Request    ┌──────────┐     SQL query     ┌──────────┐
  │  Client  │ ────────────────► │  Server  │ ─────────────────► │ Database │
  │ (browser,│                   │ (FastAPI │                    │ (MySQL)  │
  │  app)    │ ◄──────────────── │  backend)│ ◄───────────────── │          │
  └──────────┘   HTTP Response   └──────────┘     rows           └──────────┘
```

1. Le **client** envoie une **requête** (Request) : « donne-moi la liste des étudiants ».
2. Le **serveur** (notre backend) la reçoit, comprend ce qui est demandé, et vérifie les permissions et les règles.
3. Le serveur demande à la **base de données** : « SELECT tous les étudiants ». (C'est **un autre** échange client-serveur : face à la base de données, notre serveur est le client ! Nous l'avons vu dans la pratique sur les réseaux.)
4. La base de données renvoie des lignes.
5. Le serveur les traite et renvoie une **réponse** (Response) au client, généralement en **JSON** (souvenez-vous de la leçon sur JSON !).

**Pourquoi le client ne parle-t-il pas directement à la base de données ?** Parce qu'alors chaque utilisateur pourrait tout lire et tout supprimer. Le serveur est **le gardien** : il décide de ce qui est permis, vérifie la validité, et impose les règles. Exactement comme l'encapsulation dans le thème POO, mais au niveau de tout le système.

#### API — Application Programming Interface

**API** = une **interface** qu'un logiciel expose, pour que **d'autres** logiciels puissent l'utiliser. Une interface = un ensemble défini d'actions : ce que l'on peut demander, comment on le demande, et ce que l'on reçoit en retour.

Vous connaissez déjà l'idée ! En POO, l'**interface publique** d'une classe (les méthodes publiques) est exactement « l'API d'un objet ». Une **API web** est la même idée sur le réseau : au lieu de `shop.place_order(...)`, vous envoyez une requête HTTP.

| POO (le thème POO) | API web (maintenant) |
|---|---|
| `shop.get_product("P1")` | `GET /products/P1` |
| `shop.add_customer("Dana", ...)` | `POST /customers` avec un body |
| `ProductNotFoundError` | Code d'état `404` |
| Les méthodes publiques | Les endpoints |

#### L'endpoint

**Endpoint** = **une adresse de l'API + une action**. La combinaison d'une **méthode** (GET/POST...) et d'un **chemin** (Path, `/students`).

```text
GET     /students        → list all students
GET     /students/7      → get student 7
POST    /students        → create a new student
PUT     /students/7      → update student 7
DELETE  /students/7      → delete student 7
```

Ce sont **cinq endpoints différents**, même si certains partagent le même chemin. La méthode fait partie de « l'adresse ».

**Ressource** (Resource) = la « chose » que gère l'API : `students`, `products`, `orders`. Une convention en usage : le chemin au **pluriel**, et un identifiant après une barre oblique.

#### Que fait le backend à chaque requête ?

| Étape | Exemple |
|---|---|
| **Réception** — décoder la méthode, le chemin, le body | `POST /students` avec `{"name": "Dana", ...}` |
| **Validation** — les données sont-elles valides ? | L'âge est un nombre, l'e-mail contient un `@` |
| **Logique** — les règles métier | L'e-mail n'existe pas déjà |
| **Accès aux données** — la base de données | `INSERT INTO students ...` |
| **Réponse** — un code d'état + du JSON | `201 Created` + le nouvel étudiant |

### À quoi ressemble une réponse d'API

Quand le client s'adresse à une API, il envoie une **requête**, et le serveur renvoie une **réponse**. Voici à quoi ressemblent les deux — par exemple, une requête à l'API de GitHub au sujet d'un utilisateur nommé octocat :

```text
GET /users/octocat              <- the request
Host: api.github.com

HTTP/1.1 200 OK                 <- the response
Content-Type: application/json

{"login": "octocat", "name": "The Octocat", "public_repos": 8}
```

| Partie | Ce qu'elle dit |
|---|---|
| `GET /users/octocat` | La méthode et le chemin — **ce qui** est demandé |
| `200 OK` | Le code de réponse — la requête **a réussi** |
| `Content-Type: application/json` | Le corps est au format **JSON** |
| `{"login": ...}` | Les données elles-mêmes — pas de mise en forme, pas de page, seulement des données |

Une API renvoie des **données** et non un affichage : chaque client — un site web, une application mobile ou un autre programme — reçoit les mêmes données et les affiche à sa façon.

{{< box "analogy" "Analogie : un restaurant" >}}
Le convive (**le client**) n'entre pas dans la cuisine. Il commande par l'intermédiaire du serveur, selon le menu — c'est l'**API**, et chaque plat du menu est un **endpoint**. La cuisine (**le serveur**) prépare le plat, avec ce qu'il y a dans le garde-manger (**la base de données**), et le serveur le rapporte.
{{< /box >}}

Plus loin, nous apprendrons à construire nous-mêmes une API comme celle-ci, avec **FastAPI**.

### Erreur courante

**Erreur 1 : « Le frontend enregistrera les données, pourquoi a-t-on besoin d'un backend ? »** Les données dans le navigateur restent **chez un seul utilisateur**, sur un seul ordinateur, et n'importe qui peut les modifier. Un prix enregistré dans le navigateur ? Un utilisateur peut le changer en 1 NIS. **Tout ce qui doit être fiable, partagé et sécurisé vit dans le backend.**

**Erreur 2 : confondre une API et une base de données.** L'API est **la porte**. La base de données est **la réserve** derrière elle. Le client n'a jamais d'accès direct à la réserve, et passe toujours par la porte, avec ses règles.

**Erreur 3 : des chemins qui décrivent des actions au lieu de ressources.**

```text
GET  /getAllStudents
POST /createNewStudent
GET  /deleteStudent?id=7
```

La convention (appelée **REST**) : le chemin est **un nom** (la ressource), et la **méthode** est le verbe. `DELETE /students/7` et non `GET /deleteStudent`. En particulier : **GET ne modifie jamais les données**. Les navigateurs et les robots des moteurs de recherche envoient automatiquement des GET, et supprimer par un GET est la recette du désastre. (Nous développerons ce point dans le deuxième chapitre.)

### Résumé

- **Frontend** = ce que voit l'utilisateur. **Backend** = la logique, les données et la sécurité, sur le serveur.
- Le flux : **client → serveur → base de données → serveur → client**. Le serveur est le gardien : le client n'accède pas directement à la base de données.
- **API** = une interface qu'un logiciel expose à d'autres logiciels. Sur le web, via HTTP et JSON.
- **Endpoint** = méthode + chemin. `GET /students/7` et `DELETE /students/7` sont deux endpoints différents.
- La convention : chemin = **une ressource** (un nom, au pluriel). Méthode = **une action**. GET ne modifie pas les données.

<!-- docs:start — generated by scripts/intro6/site_docs.py; edit the links there -->

### Documentation officielle

- [MDN — Introduction to the server side](https://developer.mozilla.org/en-US/docs/Learn_web_development/Extensions/Server-side/First_steps/Introduction)
- [MDN Glossary — API](https://developer.mozilla.org/en-US/docs/Glossary/API)
- [MDN Glossary — JSON](https://developer.mozilla.org/en-US/docs/Glossary/JSON)

<!-- docs:end -->

## Chapitre 2 : Les méthodes HTTP et les codes d'état

### Qu'allons-nous apprendre ?

- Les quatre principales **méthodes HTTP** : **GET**, **POST**, **PUT**, **DELETE**.
- Comment elles correspondent au **CRUD** : Create, Read, Update, Delete.
- Les **codes d'état** (Status Codes) de base : quel code renvoyer et quand.
- À quoi ressemblent une requête et une réponse pour chacune des actions.

### Pourquoi en avons-nous besoin ?

Dans le thème de l'API des étudiants, vous écrirez un serveur, et pour chaque endpoint vous devrez décider : quelle méthode ? Quel code renvoyer en cas de succès, et lequel pour chaque type d'échec ? Un client qui parle à votre serveur (une application, un frontend, un autre service) décide quoi faire **selon le code** : afficher les données, afficher « introuvable », ou demander à l'utilisateur de corriger un formulaire. Un mauvais code = un client qui se comporte mal.

### Explication à partir des bases

#### Le CRUD — les quatre actions sur les données

Presque tout système fait quatre choses avec ses données :

| CRUD | Signification | Méthode HTTP | SQL (le thème des bases de données) |
|---|---|---|---|
| **C**reate | Créer | **POST** | `INSERT` |
| **R**ead | Lire | **GET** | `SELECT` |
| **U**pdate | Mettre à jour | **PUT** | `UPDATE` |
| **D**elete | Supprimer | **DELETE** | `DELETE` |

**Ce tableau, c'est toute la partie backend.** Chaque ligne sera un endpoint, et une fonction qui exécute du SQL.

#### Les quatre méthodes

**GET — lire.**

- « Donne-moi » : `GET /students`, `GET /students/7`.
- **Pas de body.** Toute l'information est dans le chemin et la query (dans la leçon suivante).
- **Ne modifie rien** sur le serveur. On dit qu'elle est **sûre** (Safe). On peut l'envoyer 100 fois, et rien ne changera.

**POST — créer.**

- « Crée quelque chose de nouveau » : `POST /students`, avec un **body** qui le décrit.
- Chaque envoi crée **un élément de plus**. Deux envois = deux étudiants.
- En général, le serveur fixe l'identifiant (`id`) et renvoie le nouvel élément.

**PUT — mettre à jour (remplacer).**

- « Mets à jour cet élément » : `PUT /students/7`, avec un **body** contenant **toutes** les nouvelles données.
- Renvoyer la même requête = le même résultat (l'étudiant reste avec les mêmes valeurs). On dit qu'elle est **idempotente** (Idempotent).

**DELETE — supprimer.**

- « Supprime cet élément » : `DELETE /students/7`.
- Généralement **pas de body**.

(Il existe d'autres méthodes, comme **PATCH** pour une mise à jour partielle de certains champs, mais ces quatre nous suffisent.)

{{< box "analogy" "Analogie : une bibliothèque de prêt" >}}
**GET** = « puis-je voir le livre ? » (vous regardez, vous ne prenez pas). **POST** = « je fais don d'un nouveau livre à la bibliothèque » (un exemplaire est ajouté). **PUT** = « remplace la couverture déchirée du livre 7 par une nouvelle » (le même livre, mis à jour). **DELETE** = « retire le livre 7 des étagères ».
{{< /box >}}

#### Les codes d'état — ce que répond le serveur

Un rappel du thème sur l'ordinateur, le système d'exploitation et le réseau : **2xx** succès, **4xx** erreur du client, **5xx** erreur du serveur. Voici les codes que nous utiliserons :

| Code | Nom | Quand le renvoyer | Exemple dans notre serveur |
|---|---|---|---|
| **200** | OK | Succès, et il y a une réponse | GET a réussi, PUT a réussi |
| **201** | Created | Une nouvelle ressource **a été créée** | POST a réussi |
| **204** | No Content | Succès, **sans** body | DELETE a réussi |
| **400** | Bad Request | La requête est invalide au regard des règles | Âge 7 (il faut 16+), un nom vide |
| **404** | Not Found | La ressource n'existe pas | `GET /students/999` |
| **409** | Conflict | En conflit avec un état existant | Un e-mail déjà enregistré |
| **422** | Unprocessable Content | La **structure** des données est fausse | Un champ manquant, du texte au lieu d'un nombre (FastAPI le renvoie automatiquement) |
| **500** | Internal Server Error | **Un bug dans le serveur** | Une exception non attrapée dans notre code |

**Le principe de décision :**

```text
Did it work?
├── yes → created something new?  → 201
│         nothing to return?      → 204
│         otherwise               → 200
└── no  → the client's fault?
          ├── resource doesn't exist        → 404
          ├── wrong structure / types       → 422
          ├── breaks a business rule        → 400
          ├── conflicts with existing data  → 409
          └── our code crashed              → 500  (fix the bug!)
```

#### 4xx face à 5xx — pourquoi est-ce important ?

- **4xx** = « **toi** (le client) dois changer quelque chose » : corriger le formulaire, ou demander quelque chose qui existe. Réessayer **sans changement** échouera à nouveau.
- **5xx** = « **moi** (le serveur) ai échoué ». Le client n'a rien fait de mal. Le code du serveur doit être corrigé.

**Un serveur qui renvoie 500 sur une mauvaise saisie de l'utilisateur contient un bug** : il aurait dû vérifier l'entrée et renvoyer un 4xx. (Vous vous souvenez du serveur de calculatrice du thème sur l'ordinateur, le système d'exploitation et le réseau, qui plantait sur « hello » ?)

### Requêtes et réponses — des exemples

Voici à quoi ressemblent les requêtes pour chacune des actions, et le code que renvoie le serveur :

```text
POST   /students     {"name": "Dana"}   -> 201 Created
GET    /students/7                      -> 200 OK
PUT    /students/7   {"name": "Dana C"} -> 200 OK
DELETE /students/7                      -> 204 No Content
GET    /students/99                     -> 404 Not Found
```

### Quand envoyer un body

| Méthode | Body ? | Ce qu'il contient |
|---|---|---|
| `GET` | Non | On ne fait que lire — il n'y a rien à envoyer |
| `POST` | **Oui** | Les données de la nouvelle ressource, en JSON |
| `PUT` | **Oui** | Toutes les données mises à jour |
| `DELETE` | Non | L'identifiant dans le chemin suffit |

Plus loin, dans FastAPI, nous verrons comment notre serveur reçoit chacune de ces requêtes et renvoie le bon code.

### Erreur courante

**Erreur 1 : un GET qui modifie des données.**

```text
GET /students/7/delete
```

Les navigateurs préchargent les liens, et les moteurs de recherche parcourent chaque lien (le crawling). Un lien comme celui-ci **supprimera des étudiants sans que personne ne l'ait voulu**. Modifier des données : uniquement POST, PUT et DELETE.

**Erreur 2 : renvoyer 200 pour tout, avec « error » dans le JSON.**

```json
{"status": "error", "message": "student not found"}
```

...avec le code 200. Le client (et aussi les navigateurs et les systèmes de surveillance) voit 200 et « pense » que tout a réussi. **Le code fait partie de la réponse.** Un étudiant qui n'existe pas = **404**.

**Erreur 3 : 500 sur une mauvaise saisie.** Un serveur qui exécute `int(age)` sans vérifier, et plante sur `"abc"` → 500. Ce n'est **pas** une erreur du client, qui ne doit pas être puni. C'est un bug du serveur. Vérifiez l'entrée, et renvoyez un **4xx** avec une explication.

**Erreur 4 : 404 face à 400.** `GET /students/999` (valide, mais n'existe pas) → **404**. `POST /students` avec l'âge `-5` (existe, mais n'est pas valide) → **400**. La question : « la ressource n'existe-t-elle pas, ou la requête n'est-elle pas valide ? »

### Résumé

- **CRUD ↔ HTTP** : Create = **POST**, Read = **GET**, Update = **PUT**, Delete = **DELETE**.
- **GET** est sûr : il ne modifie pas les données, et n'a pas de body. POST/PUT envoient un body en JSON avec `Content-Type: application/json`.
- Succès : **200** (il y a une réponse), **201** (créé), **204** (pas de contenu).
- Une erreur du client : **404** (n'existe pas), **400** (enfreint une règle), **409** (un conflit), **422** (mauvaise structure ou mauvais type).
- **500** = un bug dans le serveur. Une mauvaise saisie doit recevoir un 4xx, et ne pas provoquer de plantage.
- Le code fait partie de la réponse. Ne renvoyez pas 200 avec « error » à l'intérieur.

<!-- docs:start — generated by scripts/intro6/site_docs.py; edit the links there -->

### Documentation officielle

- [MDN — HTTP request methods](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Methods)
- [MDN — HTTP response status codes](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status)
- [MDN — HTTP messages](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Messages)

<!-- docs:end -->

<!-- exercises:start — generated by scripts/intro6/sync_site_exercises.py; edit scripts/intro6/exercises/ -->
## Exercices

Questions de compréhension sur le contenu de la leçon — sans code.

### Exercice 1: Qui fait quoi ?

Pour chaque action — se passe-t-elle dans le client, dans le serveur ou dans la base de données ?

1. L'utilisateur clique sur le bouton « S'inscrire ».
2. Vérifier que l'e-mail n'est pas encore enregistré.
3. Enregistrer le nouvel étudiant de façon durable.
4. Afficher le message « Vous vous êtes bien inscrit ».
5. Décider quel code d'état renvoyer.

{{< solution >}}
1. **Client** — l'interface que voit l'utilisateur.
2. **Serveur** — la logique et les règles (à l'aide d'une requête à la base de données).
3. **Base de données** — le stockage permanent.
4. **Client** — affiche ce que le serveur a renvoyé.
5. **Serveur** — c'est lui qui décide de ce qui s'est passé et renvoie une réponse.

```text
Client  --HTTP request-->  Server  --SQL query-->  Database
Client  <--HTTP response-- Server  <---rows------  Database
```
{{< /solution >}}

### Exercice 2: Les endpoints

Écrivez les cinq endpoints d'une API de gestion de **produits** (`/products`) : une liste, un produit, créer, mettre à jour et supprimer. Pour chacun — la méthode, le chemin et ce qu'il fait.

{{< solution >}}
```text
GET     /products      -> list all products
GET     /products/7    -> get product 7
POST    /products      -> create a new product
PUT     /products/7    -> update product 7
DELETE  /products/7    -> delete product 7
```

**Endpoint** = méthode + chemin. Le même chemin (`/products/7`) fait trois choses différentes selon la méthode.
{{< /solution >}}

### Exercice 3: Lire une réponse d'API

Un serveur a renvoyé la réponse suivante :

```text
HTTP/1.1 200 OK
Content-Type: application/json

{"login": "octocat", "name": "The Octocat", "public_repos": 8, "blog": null}
```

1. La requête a-t-elle réussi ? Comment le savez-vous ?
2. Dans quel format sont les données, et comment le savez-vous ?
3. Quel est le nom de l'utilisateur, et combien de dépôts a-t-il ?
4. Que signifie `null` ?

{{< solution >}}
1. **Oui** — le code est **200 OK**.
2. **JSON** — c'est ce que dit l'en-tête `Content-Type: application/json`, et c'est aussi ce à quoi ressemble le corps.
3. Le nom est **The Octocat**, et il a **8** dépôts.
4. `null` en JSON signifie **« aucune valeur »** — l'utilisateur n'a pas de site web (`blog`). (En Python, quand nous le lirons plus tard, il deviendra `None`.)
{{< /solution >}}

### Exercice 4: CRUD ↔ méthodes

Associez chaque action CRUD à une méthode HTTP, et au code de réponse adapté en cas de succès.

```text
Create    Read    Update    Delete
```

{{< solution >}}
| CRUD | Méthode | Code en cas de succès |
|---|---|---|
| Create | `POST` | **201** Created |
| Read | `GET` | **200** OK |
| Update | `PUT` | **200** OK |
| Delete | `DELETE` | **204** No Content |
{{< /solution >}}

### Exercice 5: Quel code renvoyer ?

Pour chaque cas — quel code d'état le serveur doit-il renvoyer ?

1. Un nouvel étudiant a été créé.
2. L'étudiant 99 a été demandé, et il n'existe pas.
3. Quelqu'un a essayé de créer un étudiant avec un e-mail déjà enregistré.
4. Un étudiant a été supprimé — et il n'y a rien à renvoyer.
5. L'âge 7 a été envoyé, mais l'âge minimum est 16.
6. Le serveur a planté à cause d'un bug dans le code.

{{< solution >}}
1. **201** — quelque chose de nouveau a été créé.
2. **404** — la ressource n'existe pas.
3. **409** — un conflit avec ce qui existe déjà.
4. **204** — succès, sans corps.
5. **400** — la requête ne respecte pas les règles (l'erreur du client).
6. **500** — l'erreur du serveur.
{{< /solution >}}

<!-- exercises:end -->
