Archives Wild Code School
Express.js

Express 02 - đŸ›°ïž MĂ©thode POST et crĂ©ation des donnĂ©es

QuĂȘte 4 sur 12 · 3 images archivĂ©es

⚠ Avant de commencer cette quĂȘte, nous te conseillons de terminer celles-ci :
QuĂȘtes liĂ©es

Dans les quĂȘtes prĂ©cĂ©dentes, tu as appris Ă  :

  • Configurer et crĂ©er un serveur avec Express
  • CrĂ©er des routes basiques
  • CrĂ©er des routes GET qui rĂ©cupĂšre les informations de la base de donnĂ©es.

Dans cette quĂȘte, il est temps d'apprendre Ă  Ă©crire des routes POST avec Express et Ă  insĂ©rer de nouveaux Ă©lĂ©ments dans notre base de donnĂ©es via HTTP !

NASA reduced gravity

đŸ€“ Dans cette quĂȘte, tu vas apprendre Ă  :

✅ CrĂ©er une route POST ✅ Enregistrer les donnĂ©es dans la base de donnĂ©es Ă  partir d'une requĂȘte POST

📬 Comment crĂ©er une route POST avec Express ?

D'une certaine maniĂšre, tu connais dĂ©jĂ  la rĂ©ponse... Si tu te souviens de cette requĂȘte :

http
GET http://localhost:5000/api/movies

Tu as déclaré une route pour y répondre comme ceci :

javascript
app.get("/api/movies", HANDLER);

Maintenant, tu veux gĂ©rer les requĂȘtes de crĂ©ation de ressources, comme celle-ci :

http
POST http://localhost:5000/api/movies
Content-type: application/json

{
  "title": "Citizen Kane",
  "director": "Orson Wells",
  "year": "1941",
  "color": "0",
  "duration": 120
}

Prenons cet exemple de création d'un film dans la table movies :

quiz
false|||true|||false
# Quelle méthode de `app` dois tu utiliser pour déclarer la route ?
[x] `app.post()`
[] `app.get()`
[] `app.delete()`
[] `app.put()`
# Quel chemin dois-tu utiliser comme premier paramÚtre ?
[] `"/api/movies/:id"`
[x] `"/api/movies"`
[] `"/api/users"`
[] `"/api/users/:id"`

C'est suffisant pour un premier jet. Essaye de crĂ©er la route pour POST /api/movies : pour cette Ă©tape, envoie "Post route is working 🎉" dans la rĂ©ponse.

hidden
Afficher la solution|||javascript|||Tu as des doutes sur comment faire ?|||0|||Masquer
// in src/controllers/movieControllers.js

const postMovie = (req, res) => {
  res.send("Post route is working 🎉");
};

module.exports = {
  getMovies,
  getMovieById,
  postMovie, // don't forget to export your function ;)
};

// in src/app.js

app.post("/api/movies", movieControllers.postMovie);

Maintenant, lançons Postman et faisons une requĂȘte POST !

Tape l'URL localhost:5000/api/movies puis sĂ©lectionne POST dans le menu dĂ©roulant. Clique sur Envoyer, tu devrais voir Post route is working 🎉.

đŸ€·đŸ»â€â™‚ïž Mais une requĂȘte POST n'est-elle pas supposĂ©e contenir des informations ?

Bien sĂ»r que oui ! Ajoutons un corps Ă  notre requĂȘte avec Postman !

Clique sur l'onglet body et sélectionne raw. Sélectionne ensuite JSON à l'aide du menu déroulant :

Select JSON using the dropdown menu

À l'intĂ©rieur du corps, plaçons les donnĂ©es d'un nouveau film au format JSON :

json
{
  "title":"Whiplash",
  "director" :"Damien Chazelle",
  "year":"2014",
  "color":true,
  "duration":107
}

Si tu cliques sur SEND, rien ne se passera. Car nous n'avons encore rien écrit pour "rattraper" les données dans Express. Pour cela, tu dois utiliser req.body (le code suivant ne fonctionnera pas)  :

javascript
const postMovie = (req, res) => {
  console.log(req.body);
  res.send("Post route is working 🎉");
};

Essaye d'envoyer Ă  nouveau la demande avec Postman. Maintenant, tu devrais voir undefined dans la console. Et c'est parfaitement normal !

Express ne peut pas lire les corps de requĂȘte JSON par dĂ©faut... Pour que cela fonctionne, nous devons utiliser un middleware express intĂ©grĂ© : express.json(). Modifie le code de ton fichier app.js comme suit :

javascript
const express = require("express");

const app = express();

app.use(express.json()); // add this line

// ...

Maintenant rĂ©essaye d'envoyer les donnĂ©es avec Postman : tu devrais voir les donnĂ©es dans le terminal oĂč tu as lancĂ© le serveur.

Middle-quoi ?

Par définition, un middleware est un logiciel (ou une fonction) qui sera appelé entre deux parties d'un logiciel (ou deux opérations, ou deux applications).

Une application utilisant Express n'est rien d'autre qu'une succession d'appels middleware.

Ne t'inquiÚte pas si les middlewares sont encore un peu déroutants pour le moment, nous les verrons et les pratiquerons plus tard.

Ce que tu dois garder Ă  l'esprit, c'est que express.json() est un middleware que nous utilisons au tout dĂ©but de notre code pour nous assurer que toutes nos routes sont capables de lire un corps de requĂȘte au format JSON.

Insérer des données dans ta base de données

Dans les Ă©pisodes prĂ©cĂ©dents, tu as utilisĂ© des requĂȘtes SELECT : maintenant nous devons INSÉRER des donnĂ©es.

Dans ta fonction pour poster, utilise la déstructuration d'objet pour créer une variable pour chaque propriété de req.body.

javascript
const postMovie = (req, res) => {
  const { title, director, year, color, duration } = req.body;
};

đŸ‘ŒđŸ» En extrayant toutes les variables, nous nous assurons de n'envoyer Ă  notre base de donnĂ©es que les informations que nous souhaitons INSÉRER.

L'Ă©tape suivante consiste Ă  utiliser database.query pour Ă©crire ta requĂȘte INSERT. Cela devrait commencer comme ceci :

javascript
const postMovie = (req, res) => {
  const { title, director, year, color, duration } = req.body;

  database
    .query(
      "INSERT INTO movies(title, director, year, color, duration) VALUES (?, ?, ?, ?, ?)",
      [title, director, year, color, duration]
    )
    .then(([result]) => {
      // wait for it
    })
    .catch((err) => {
      console.error(err);
      res.sendStatus(500);
    });
};

Note que nous utilisons plusieurs ? prĂšs du mot-clĂ© SQL VALUES. Ces points d'interrogation seront remplacĂ©s par le module mysql2 avant que la requĂȘte ne soit rĂ©ellement envoyĂ©e Ă  la base de donnĂ©es. C'est lĂ  que les valeurs du tableau en deuxiĂšme argument seront utilisĂ©es. Attention, l'ordre des Ă©lĂ©ments dans le tableau compte ! Le premier point d'interrogation sera remplacĂ© par le premier Ă©lĂ©ment du tableau et ainsi de suite...

En regardant la partie then, c'est lĂ  que nous obtenions prĂ©cĂ©demment les lignes sĂ©lectionnĂ©es lors de l'exĂ©cution d'une requĂȘte SELECT. Mais nous effectuons maintenant une requĂȘte INSERT : le rĂ©sultat est ici le rĂ©sultat d'une insertion. Si tu le console.log(), tu seras peut-ĂȘtre intĂ©ressĂ© par result.insertId qui stocke l'identifiant auto-incrĂ©mentĂ© de la ressource insĂ©rĂ©e.

Passons Ă  la derniĂšre partie du puzzle. Si tu lis cette page (et que tu la mets dans tes favoris), tu sauras qu'une requĂȘte POST doit renvoyer :

  • le statut HTTP "Created"
  • un en-tĂȘte Location pointant vers la nouvelle ressource (quelque chose comme /api/movies/ suivi de l'identifiant d'insertion)... cette partie ajouterait beaucoup de complexitĂ© et est donc rarement suivie dans l'usage : nous allons privilĂ©gier un objet contenant l'id.
js
res.status(/* ??? */).send({ id: /* ??? */ });

Essaye de terminer la fonction par toi-mĂȘme.

hidden
Afficher la solution|||javascript|||Tu as des doutes sur comment faire ? |||0|||Masquer
const postMovie = (req, res) => {
  const { title, director, year, color, duration } = req.body;

  database
    .query(
      "INSERT INTO movies(title, director, year, color, duration) VALUES (?, ?, ?, ?, ?)",
      [title, director, year, color, duration]
    )
    .then(([result]) => {
      res.status(201).send({ id: result.insertId });
    })
    .catch((err) => {
      console.error(err);
      res.sendStatus(500);
    });
};

Retourne maintenant Ă  Postman et renvoie la requĂȘte !

Tu devrais voir le statut 201 Created et l'id dans le corps de la réponse.

Tu peux maintenant refaire une requĂȘte GET pour vĂ©rifier si les donnĂ©es ont bien Ă©tĂ© envoyĂ©es :

GET movies

đŸ’Ș Challenge

Insérer des utilisateurs dans la base de données

Maintenant que tu as créé la route POST pour les films, créons la route POST pour conserver les nouveaux utilisateurs.

  • CrĂ©e une route POST pour /api/users qui insĂ©rera un nouvel utilisateur dans la base de donnĂ©es
  • Publie un lien GitHub pour partager ta solution

🧐 Critùres d'acceptation

  • [ ] Le GitHub contient une route POST pour les utilisateurs
  • [ ] Une requĂȘte POST sur /api/users devrait crĂ©er un nouvel utilisateur dans la base de donnĂ©es

==$==

Ce que tu devrais avoir dans :

javascript
// ...

const movieHandlers = require("./movieHandlers");

app.get("/api/movies", movieHandlers.getMovies);
app.get("/api/movies/:id", movieHandlers.getMovieById);
app.post("/api/movies", movieHandlers.postMovie);

const userHandlers = require("./userHandlers");

app.get("/api/users", userHandlers.getUsers);
app.get("/api/users/:id", userHandlers.getUserById);
app.post("/api/users", userHandlers.postUser);

// ...
javascript
// ...

const postUser = (req, res) => {
  const { firstname, lastname, email, city, language } = req.body;

  database
    .query(
      "INSERT INTO users(firstname, lastname, email, city, language) VALUES (?, ?, ?, ?, ?)",
      [firstname, lastname, email, city, language]
    )
    .then(([result]) => {
      res.status(201).send({ id: result.insertId });
    })
    .catch((err) => {
      console.error(err);
      res.sendStatus(500);
    });
};

module.exports = {
  getUsers,
  getUserById,
  postUser,
};
javascript
// ...

const postMovie = (req, res) => {
  const { title, director, year, color, duration } = req.body;

  database
    .query(
      "INSERT INTO movies(title, director, year, color, duration) VALUES (?, ?, ?, ?, ?)",
      [title, director, year, color, duration]
    )
    .then(([result]) => {
      res.status(201).send({ id: result.insertId });
    })
    .catch((err) => {
      console.error(err);
      res.sendStatus(500);
    });
};

module.exports = {
  getMovies,
  getMovieById,
  postMovie,
};