--- title: Développer une API REST en NodeJS tags: backend, nodejs, support robots: noindex, nofollow author: Julien Noyer --- # Développer une API REST en NodeJS *Interface de programmation pour applications Javascript* ![](https://i.imgur.com/d0fcfTE.png) *All rights reserved for educational purposes only © 2021-2022 [Julien Noyer](https://www.linkedin.com/in/julien-n-21219b28/)* --- <br> ## Traitement de l'information et protocole HTTP Une [interface de programmation](https://fr.wikipedia.org/wiki/Interface_de_programmation), plus communément appelée API, est une application constituée d'un ensemble de fonctions et de méthodes pour on pour but de gérer le transfert d'informations entre applications. Elle prend la forme d'un [service web](https://fr.wikipedia.org/wiki/Service_web), c'est à dire qu'elle est disponible en ligne via le [protocole HTTP](https://fr.wikipedia.org/wiki/Hypertext_Transfer_Protocol). Dans la meesurr ou le traitement de l'information est au centre du Web L'API est devenue central dans la plupart des projets Web, nous parlons donc aujourd'hui du principe de [API-First Approach](https://swagger.io/resources/articles/adopting-an-api-first-approach/) dans le développement de projet Web. Ce principe qui consiste à commencer par structurer une API comme point de départ du développement d'un projet induit de respecter des normes afin de rendre nos API accessibles et structurées. C'est pourquoi ce document va prendre le partie de présenter une méthode de développement qui correspond aux critères des [API REST](https://fr.wikipedia.org/wiki/Representational_state_transfer) qui représentent aujourd'hui la norme la plus utilisée. <br><br> ## Différents environemnts mais une approche identique ![](https://i.imgur.com/ON0osxC.png) Quelque soit le choix de l'environement pour développer une API, que ce soit [PHP](https://www.php.net/docs.php), [Javascrypt](https://developer.mozilla.org/en-US/docs/Web/javascript), [Python](https://www.python.org/doc/) ou autre, les logiques d'API REST sont à respecter peu importe le langage utilisé pour la développer. L'architecture REST (Representational State Transfer) ou RESTful permet de construire des applications (Web, Intranet, Web Service, ...) en suivant ensemble de conventions et de bonnes pratiques à respecter et non d’une technologie à part entière déclinées sur 5 règles : - L’URI comme identifiant des ressources - Les verbes HTTP comme identifiant des opérations (GET, PUT, ...) - Les réponses HTTP comme représentation des ressources - Les liens comme relation entre ressources - Un paramètre comme jeton d’authentification Nous allons à présent aborder la mise en place d'une API REST en [NodeJS](https://nodejs.org/en/) et [ExpressJS](https://expressjs.com) mais lees principes qui sont présentés dans cee document peuvent être adaptés à d'autres technologie. --- <br><br><br><br><br><br> # Structurer une API REST NodeJS *Organisation du projet et modules de base* ![](https://i.imgur.com/tZhTBG0.png) ## Démarrer un projet NodeJS NodeJS est une plateforme logicielle libre en JavaScript orientée vers les applications réseau événementielles hautement concurrentes qui doivent pouvoir monter en charge. Elle utilise la [machine virtuelle V8](https://fr.wikipedia.org/wiki/V8_(moteur_JavaScript)), la librairie [libuv](https://en.wikipedia.org/wiki/Libuv) pour sa boucle d'évènements, et implémente sous [licence MIT](https://fr.wikipedia.org/wiki/Licence_MIT) les spécifications [CommonJS](https://fr.wikipedia.org/wiki/CommonJS). Initialement développé par [Ryan Dahl](https://github.com/ry), NodeJS est un projet [OpenSource](https://fr.wikipedia.org/wiki/Open_source) dont l'engouement grandi de plus en plus depuis sa mise en production et se revèle être un outil idéal pour développer une API REST. Dans un premier temps nous allons télécharger NodeJS depuis la page https://nodejs.org/fr/download/, l'installer et tester l'installation avec les commandes suivantes dans un invite de commande : ``` node -v npm - v ``` > C'est deux commandes doivent vous afficher les version de `node` et `npm`. Pour bien débuter le développement d’une API REST avec NodeJS il est important de respecter une structure et de correctement organiser les différents fichiers qui seront utilisés dans l’API. Il est donc important de sélectionner un dossier spécifique sur la machine locale dans laquelle sera développée l’API. Nous sélectionnons le dossier contenant nos différrentes projets pour y créér un nouveau dossier nommé `NODEapi` organisé de la façon suivante : ``` NODEapi - models - routers - services - www ``` > Nous utiliserons le dossier `www` uniquement pour rendre la route `/` accessible, nous y ajoutons simplement un fichier `index.html`. Une fois le dossier créé nous nous plaçon dedans en invitre de command et nous tapons la commande suivante pour initialiser notre projet NodeJS : ``` git init npm init -y ``` A la fin de cette commande le terminal affiche le code suivant poour nous indiquer le sucess de l'initialisation : ``` Wrote to /path/to/NODEapi/package.json: { "name": "NODEapi", "version": "1.0.0", "description": "", "main": "server.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "start": "node server.js" }, "keywords": [], "author": "", "license": "ISC" } ``` ## Structure de base d'un projet NodeJS Le principe souvent mit en place dans le développement NodeJS et d'utiliser un certain nombre de [modules NPM](https://www.npmjs.com) qui permettent de faciliter le développement en utilisant des bibliothèques de codes. Nous allons donc commencer par en importer dans le fichier `server.js` : ```javascript= /* Imports */ // Modules require('dotenv').config(); const express = require('express'); const bodyParser = require('body-parser'); const ejs = require('ejs'); const path = require('path'); // ``` Puis nous ajoutons les ces modules een tapant la commande suivante dans le dossier de notre API : ``` npm i -s dotenv express body-parser ejs path ``` Le module [Dotenv](https://www.npmjs.com/package/dotenv) permet de gérer plus facilement les [varibables d'environement serveur](https://fr.wikipedia.org/wiki/Variable_d%27environnement) qui sont très utiles pour sécuriser certaines données que nous utiliserons dans notre code. Nous créons donc un fichier `.env` à la racine de notrre projet : ``` touch .env ``` Puis nous ouvrons le fichier `.env` pour y ajouter la variable d'environenement suivante : ``` PORT=6985 ``` > Nous ajoutons le fichier `.env` dans le fichier `.gitignore` car il ne faut surtout pas partager les variables d'enrironement. Nous pouvons à présent commencer à mettre en place la structure de notre API NodeJS. Nous allons prendre le principe des [classes Javascript](https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Classes) pour configurer notre serveur, nous nous plaçons à la fin du fichier `server.js` pour créer des constantes et une classe nommée `ServerClass` : ```javascript= /* Declarations */ const server = express(); const port = process.env.PORT; // /* Server class */ class ServerClass{ constructor(){} init(){ this.config() }; config(){ this.launch() }; launch(){ server.listen(port, () => { console.log(`http://localhost:${port}`); }); }; } // ``` Cette structure nous permet de décomposer les différerntes étapes dee configuration de notre serveur et le fait qu'elle prenne la forme d'une classe nous permettrra reprendre notre code facielemnt pourr un autre projet. Nous nous plaçons à présent à la fin du code pour lancer notre serveur : ```javascript= /* Start server */ const NODEapi = new ServerClass(); NODEapi.init(); // ``` <br> ## Initialiser un projet NodeJS La classe `ServerClass` intègre une méthode `init()` que nous utilisons pour initialiser notre serveur. Nous allons donc y ajouter le code suivant : ```javascript= init(){ // View engine configuration server.engine( 'html', ejs.renderFile ); server.set( 'view engine', 'html' ); // Static path configuration server.set( 'views', __dirname + '/www' ); server.use( express.static(path.join(__dirname, 'www')) ); //=> Body-parser server.use(bodyParser.json({limit: '10mb'})); server.use(bodyParser.urlencoded({ extended: true })); // Start server configuration this.config(); }; ``` Dans cette méthode nous définition dans un premier temps le [moteur de rendu](https://fr.wikipedia.org/wiki/Moteur_de_rendu) utiliser pour notre API, nous utilisons [EJS](https://www.npmjs.com/package/ejs) pourr définir le format [HTML](https://fr.wikipedia.org/wiki/Hypertext_Markup_Language) comme moteur. Puis nous utilisons [Path](https://www.npmjs.com/package/path) pour identifier le dossier `www` comme origine pour les fichier statiques puis nous configurons [BodyParser](https://www.npmjs.com/package/body-parser) pourr permettre à nous API NodeJS de lire le contenu du corps des requêtes HTTP. <br> ## Configurer les routes de l'API La méthode `config()` est utiliser pour configurer les routeurs de notre API. Nous allons donc dans un premier temps créer un fichier nommé `crud.router.js` dans le dossier `routers` eet nous y ajoutons le code suivant : ```javascript= /* Imports */ const express = require('express'); const router = express.Router(); // /* Routes definition */ class CrudRouterClass { constructor() {} // Set route fonctions routes(){}; // Start router init(){ // Get route fonctions this.routes(); // Sendback router return router; }; }; // /* Export */ module.exports = CrudRouterClass; // ``` Nous conservons le principe de classe pourr structure notre router ce qui nous permet de l'importer danss la méthode `config()` de la class `ServerClass` dee la façon suivante : ```javascript= config(){ // Set auth router const CrudRouterClass = require('./routers/crud.router'); const crudRouter = new CrudRouterClass(); server.use('/api', crudRouter.init()); // Set front router server.get('/*', (req, res) => res.render('index') ); // Launch server this.launch(); }; ``` > La méthode `config()` défini également la route `/*` qui renvoie toutes les requêtes vers le front sur le fichier `indeex.html` du dossier `www`. --- <br><br><br><br><br><br> # Mise en place d'un CRUD en NodeJS *Les méthodes (verbes) HTTP comme base de développement* ![](https://i.imgur.com/Gh93lOr.jpg) ## Configurer un router basé sur les méthodes HTTP Comme définie dans les 5 règles de bases dans la mise en place d'une API REST est de concidérer les verbes HTTP comme identifiant des routes de l'API, il est alors essentiel de pouvoir structurer les routeurs de l'API en y intégrant les fonctions qui permettent de traiter les informations. C'est pourquoi nous allons ajouter dans la méthode `routes()` du fichier `crud.router.js` les fonctions qui correspondent au principe du [CRUD](https://fr.wikipedia.org/wiki/CRUD) : **Méthode POST** ```javascript= routes(){ router.post('/:endpoint', (req, res) => { return res.json({ method: 'POST', route: `/api/${req.params.endpoint}`, input: req.body, output: null }) }); } ``` **Méthode GET** ```javascript= routes(){ ... router.get('/:endpoint', (req, res) => { return res.json({ method: 'GET', route: `/api/${req.params.endpoint}`, input: null, output: null }) }); } ``` **Méthode GET :_id** ```javascript= routes(){ ... router.get('/:endpoint/:id', async (req, res) => { return res.json({ method: 'GET', route: `/api/${req.params.endpoint}/${req.params.id}`, input: null, output: null }) }); } ``` **Méthode PUT :_id** ```javascript= routes(){ ... router.put('/:endpoint/:id', (req, res) => { return res.json({ method: 'PUT', route: `/api/${req.params.endpoint}`, input: req.body, output: null }) }); } ``` **Méthode DELETE :_id** ```javascript= routes(){ ... router.delete('/:endpoint/:id', (req, res) => { return res.json({ method: 'DELETE', route: `/api/${req.params.endpoint}`, input: req.body, output: null }) }); } ``` Les méthodes que nous venons d'ajouter sont prévue pour pouvoir fonctionner pour n'importe quelle informations à traiter dans n'importe quel type de format de données. Ces méthodes intégre les notions de [endpoints](https://smartbear.com/learn/performance-monitoring/api-endpoints/) et d'[object identifier](https://fr.wikipedia.org/wiki/OID) pour identifier l'information à traiter et, dans le cas des méthodes `post()`, `put()` et `delete()`, la récupération des informations envoyées par le client dans le corps des requêtes HTTP. <br><br> ## API REST et base de données NOsql Dans la mesure ou le format [JSON](https://fr.wikipedia.org/wiki/JavaScript_Object_Notation) est idéal dans le traitement de l'information en Javascript, nous alons dans un premier temps intégrer dans notre API la connexion à une [base de données NOsql](https://fr.wikipedia.org/wiki/NoSQL). Nous devons dans un premier temps créer un fichier nommé `mongo.class.js` dans le dossier `services` pour gérer la connexion à une base de données [MongoDB](https://fr.wikipedia.org/wiki/MongoDB) avec le module [Mongoose](https://www.npmjs.com/package/mongoose). Nous devons donc installer le module Mongoose et créer notre fichier : ``` npm i -s mongoose touch services/mongo.class.js ``` Nous ouvrons à présent ce fichiere pour y ajouter le code suivant : ```javascript= /* Import */ // NPM moodules const mongoose = require('mongoose'); //=> https://www.npmjs.com/package/mongoose // /* Define class */ class MONGOClass { constructor(){ // Set MongoDB url this.mongoUrl = process.env.MONGO_URL; }; connectDb(){ return new Promise( (resolve, reject) => { mongoose.connect(this.mongoUrl, { useNewUrlParser: true }) .then( db => resolve( { db: db, url: this.mongoUrl } )) .catch( dbErr => reject(`MongoDB not connected`, dbErr) ) }); }; }; // /* Export class */ module.exports = MONGOClass; // ``` Le code suivant configurre la connexion à MonngoDB grâce à une nouvelle classe nommée `MONGOclass`. Cette classe intégrer une variable d'environement qu'il faut ajoouter dans le fichier `.env` : ``` MONGO_URL = 'mongodb://127.0.0.1:27017/api-node ``` > La fin de l'URL correspond à nom de la base de données MongoDB Le principe de la classe `MONGOclass` et de lancer la connexion entre l'API NodeJS et le serveur d base de données MongoDB dans la méthode `connectDB()` qui renvoie les informations de la base de données dans une [Promise](https://developer.mozilla.org/fr/docs/Web/JavaScript/Guide/Utiliser_les_promesses). Nous allons à présent ajouter ce service dans le fichier `server.js` pour l'injecter dans le constructeur : ```javascript= const MONGOclass = require('./services/mongo.class'); ``` Puis nous injectons la classe `MONGOclass` dans la class `ServerClass` en créant une propriété `MONGO`: ```javascript= constructor(){ this.MONGO = new MONGOclass; } ``` La propriété `MONGO` nous permet à présent d'accéder aux méthode de la classe `MONGOclass` dans la méthode `launch()` de la classe `ServerClass`. Le principe est donc de connecter la base de données MongoDB avant de lancer le serveur : ```javascript= launch(){ // Connect MongoDB this.MONGO.connectDb() .then( db => { // Start server server.listen(port, () => { console.log({ node: `http://localhost:${port}`, mongo: db.url }); }); }) .catch( dbErr => console.log('MongoDB Error', dbErr)); }; ``` A présent, poour pouvoi utiliser la base de données MongoDB nous devons créer un nouveau fichier qui permet de structurer les objet que nous allons ajouter dans les collection de données de notre base. Le principe avec Mongoose et de créer un `schema` qui permet de définir les propriétés des object d'un colleection, nous allons donc ajouter un fichier nommé `post.schema.js` dans le dossier `models` : ``` touch models/post.schema.js ``` Nous partons du principe que notre API traite des articles constitué d'un sujet, un titre et un contenu. Nous ouvrons donc le fichier `post.schema.js` pour y ajouter le code suivant : ```javascript= /* Import */ const mongoose = require('mongoose'); const { Schema } = mongoose; // /* Definition */ const MySchema = new Schema({ title: String, content: String }); // /* Export */ const MyModel = mongoose.model('post', MySchema); module.exports = MyModel; // ``` A présent, pour pouvoir utiliser `schema`nous devons l'importer dans la classe `CrudRouterClass` de la façon suivante : ```javascript= const PostModel = require('../models/post.schema'); ``` > Il va de soit qu'il faut créer autant de `schema` qu'il y à de collections à gérer dans la base de données MongoDB. <br><br> ## API REST et base de données SQL Bien que priorisé il est poossible de ne pas utiliser de base de données NOsql ou profit d'une [base de données relationnelles](https://fr.wikipedia.org/wiki/Base_de_données_relationnelle) comme [MySQL](https://fr.wikipedia.org/wiki/MySQL). Ce principe peut permettre par exemple d'ajouter un micro service à une applicatioon existante qui serait developpée sur la [stack LAMP](https://fr.wikipedia.org/wiki/LAMP). Le principe est très proche, nous deevons dans un premier temps créer un fichier de service nommé `mysql.class.js` dans le dossier `services` : ``` touch services/mysql.class.js ``` Puis nous créons une classe `MYSQLclass` dans laquelle nous ajoutons le codee suivant pour connecter la base de données MySql : ```javascript= /* Import */ // NPM moodules const mysql = require('mysql'); //=> https://www.npmjs.com/package/mysql // /* Define class */ class MYSQLClass { constructor(){ // Set MySQL connection this.connection = mysql.createConnection({ host : process.env.MYSQL_HOST, port : process.env.MYSQL_PORT, user : process.env.MYSQL_USER, password : process.env.MYSQL_PASS, database : process.env.MYSQL_DB }); }; connectDb(){ return new Promise( (resovle, reject) => { // Try to connect MYsql this.connection.connect( (connectionError) => { return connectionError ? reject(connectionError) : resovle(this.connection); }); }); }; }; // /* Export class */ module.exports = MYSQLClass; // ``` Le code suivant configure la connexion à MySql grâce à une nouvelle classe nommée `MYSQLClass`. Cette classe intégrer une variable d'environement qu'il faut ajouter dans le fichier `.env` : ``` MYSQL_HOST=localhost MYSQL_PORT=8889 MYSQL_USER=root MYSQL_PASS=root MYSQL_DB=api-node ``` La classse `MYSQLclass` intègre la méthodee `connectDb()` de la même manière que la classe `MONGOclass`, pour utiliser cette méthode nous devons dans un premier temps importer la classe `MYSQLclass` dans le fichier `server.js` : ```javascript= const MYSQLClass = require('./services/mysql.class'); ``` Puis nous injectons la classe `MYSQLclass` dans la class `ServerClass` en créant une propriété `MYSQL`: ```javascript= constructor(){ this.MYSQL = new MYSQLClass; } ``` La propriété `MYSQL` nous permet à présent d’accéder aux méthode de la classe `MYSQLclass` dans la méthode `config()` de la classe `ServerClass`. Le principe est donc de connecter la base de données MySQL avant de configurer les routes : ```javascript= config(){ // Connect the DB this.MYSQL.connectDb() .then( connection => { // Set auth router const CrudRouterClass = require('./routers/crud.router'); const crudRouter = new CrudRouterClass(connection); server.use('/api', crudRouter.init()); // Set front router server.get('/*', (req, res) => res.render('index') ); // Launch server this.launch(); }) .catch( connectionError => { console.log(`MYsql connection error: ${connectionError}`) }) }; ``` A présent, pour utiliser la base de données MySQL il faut injecter l'objet `connection` dans la classe `CrudRouterClass` car il permettra d'éxécuter les méthodes du CRUD. Nous ouvons donc lee fichier `crud.router.js` pour créer une propriété `connection` dans le constructeur de la classe `CrudRouterClass` : ```javascript= constructor(connection) { this.connection = connection; } ``` Le fait d'utiliser une base de donnée MySQL induit que pour chaque informations à traiter dans l'API il faudra configurer autant de table avant de pouvoir tester les fonctions du CRUD. <br><br> ## Créer, lire, éditer ou supprimer des données Nous allons aborder à présent des techniques plus spécifiques pour finaliser les méthodes du CRUD dans le fichier `crud.router.js`, à la fois avec MongoDB et MySQL. Nous partons du principe que les routes intégrent un à deux paramêtres : - **:endpoint** : qui permet d'identifier la collection MongoDB ou la table MySQL - **:id** : qui permet d'identifier un objet MongoDB ou un item MySQL Lorsque que nous avons intégrer et configurer le module [Body Parser](https://www.npmjs.com/package/body-parser) dans le fichier `server.js` nous avons ajouter à notre API la capacité d'analyser le corps des requêtes HTTP. Nous concidérons donc que pour les routes dont le endpoint est `post` pour les méthodes `post()`, `put()` et `delete()` qu'un client envoie dans le corps de ses requêtes l'objet JSON suisant : ```jsonld= { "title": "At vero eos et accusamus", "content": "Lorem ipsum dolor sit amet, consectetur..." } ``` <br> ### La méthode post() pour créer des données La première méthode que nous allons mettre à jour dans le fichier `crud.router.js`est celle qui nouus permeet d'ajouter des données dans une base de données. La méthodee `create()` de Mongoose renvoie une Promise : ```javascript= // Create MongoDB document router.post('/:endpoint', (req, res) => { PostModel.create(req.body) .then( document => res.status(201).json({ method: 'POST', route: `/api/${req.params.endpoint}`, data: document, error: null, status: 201 })) .catch( err => res.status(502).json({ method: 'POST', route: `/api/${req.params.endpoint}`, data: null, error: err, status: 502 })); }); ``` La méthode `query()` du module MySQL permet d'éxecuter des requêtes SQL classiques comme par exemple `INSERT` pour inserer des données dans une base : ```javascript= // Create one MySQL item router.post('/:endpoint', (req, res) => { this.connection.query(`INSERT INTO ${req.params.endpoint} SET ?`, req.body, (err, document) => { if (err) { return res.status(502).json({ method: 'POST', route: `/api/${req.params.endpoint}`, data: null, error: err, status: 502 }); } else{ return res.status(201).json({ method: 'POST', route: `/api/${req.params.endpoint}`, data: document, error: null, status: 201 }); }; }); }); ``` <br> ### La méthode get() pour lire des donnéees Pour lire des information il faut définir deux méthode `get()`, la première permet de récupérer toutes les information d'une collection et la deeuxième pour lire les information d'un document spécifique : ```javascript= // Read all MongoDB documents router.get('/:endpoint', (req, res) => { PostModel.find() .then( documents => res.status(200).json({ method: 'GET', route: `/api/${req.params.endpoint}`, data: documents, error: null, status: 200 })) .catch( err => res.status(502).json({ method: 'GET', route: `/api/${req.params.endpoint}`, data: null, error: err, status: 502 })); }); // Read one MongoDB document router.get('/:endpoint/:id', (req, res) => { PostModel.findById(req.params.id) .then( document => res.status(200).json({ method: 'GET', route: `/api/${req.params.endpoint}/${req.params.id}`, data: document, error: null, status: 200 })) .catch( err => res.status(502).json({ method: 'GET', route: `/api/${req.params.endpoint}/${req.params.id}`, data: null, error: err, status: 502 })); }); ``` Pour lire les informations d'une base de données MySQL il faut utiliser la requête `SELECT` SQL : ```javascript= // Read all MySQL items router.get('/:endpoint', (req, res) => { this.connection.query(`SELECT * FROM ${req.params.endpoint}`, (err, items) => { if (err) { return res.status(502).json({ method: 'GET', route: `/api/${req.params.endpoint}`, data: null, error: err, status: 502 }); } else{ return res.status(200).json({ method: 'GET', route: `/api/${req.params.endpoint}`, data: items, error: null, status: 200 }); }; }); }); // Read one MySQL item router.get('/:endpoint/:id', (req, res) => { this.connection.query(`SELECT * FROM ${req.params.endpoint} WHERE id=${req.params.id}`, (err, item) => { if (err) { return res.status(502).json({ method: 'GET', route: `/api/${req.params.endpoint}/${req.params.id}`, data: null, error: err, status: 502 }); } else{ return res.status(200).json({ method: 'GET', route: `/api/${req.params.endpoint}/${req.params.id}`, data: item, error: null, status: 200 }); }; }); }); ``` <br> ### La méthode put() pour mettre à des données Lee principe pour éditer une information est de l'identifier grâce à sont `id`, c'est pourquoi la méthode `put()` intègre le pramêtre `id` dans chaque requête. Avec MongoDB, il faut dans un premier temps rechercher le document à éditer poour ensuite le mettre à jour : ```javascript= // Update MongoDB document router.put('/:endpoint/:id', (req, res) => { PostModel.findById(req.params.id) .then( document => { // Update document document.title = req.body.title; document.content = req.body.content; // Save document document.save() .then( updatedDocument => res.status(200).json({ method: 'PUT', route: `/api/${req.params.endpoint}/${req.params.id}`, data: updatedDocument, error: null, status: 200 })) .catch( err => res.status(502).json({ method: 'PUT', route: `/api/${req.params.endpoint}/${req.params.id}`, data: null, error: err, status: 502 })); }) .catch( err => res.status(404).json({ method: 'PUT', route: `/api/${req.params.endpoint}/${req.params.id}`, data: null, error: err, status: 404 })); }); ``` Pour éditer les informations un item d’une base de données MySQL il faut utiliser la requête `UPDATE` SQL : ```javascript= // Update one MySQL item router.put('/:endpoint/:id', (req, res) => { this.connection.query(` UPDATE ${req.params.endpoint} SET title = "${req.body.title}", content = "${req.body.content}" WHERE id = ${req.params.id} `, req.body, (err, document) => { if (err) { return res.status(502).json({ method: 'PUT', route: `/api/${req.params.endpoint}/${req.params.id}`, data: null, error: err, status: 502 }); } else{ return res.status(200).json({ method: 'PUT', route: `/api/${req.params.endpoint}/${req.params.id}`, data: document, error: null, status: 200 }); }; }); }); ``` <br> ### La méthode delete() pour supprimer à des données La ddernière méthode à mettre en place permet de supprimer une donnée, elle intègre la même logique de paramêtre `id` que la méthode `put()` : ```javascript= // Delete MongoDB document router.delete('/:endpoint/:id', (req, res) => { PostModel.findOneAndDelete({ _id: req.params.id }) .then( deletedDocument => res.status(200).json({ method: 'DELETE', route: `/api/${req.params.endpoint}/${req.params.id}`, data: deletedDocument, error: null, status: 200 })) .catch( err => res.status(404).json({ method: 'DELETE', route: `/api/${req.params.endpoint}/${req.params.id}`, data: null, error: err, status: 404 })); }); ``` Pour supprimer un item d’une base de données MySQL il faut utiliser la requête `DELETE` SQL : ```javascript= // Delete one MySQL item router.delete('/:endpoint/:id', (req, res) => { this.connection.query(` DELETE FROM ${req.params.endpoint} WHERE id = ${req.params.id} `, req.body, (err, deletedDocument) => { if (err) { return res.status(502).json({ method: 'DELETE', route: `/api/${req.params.endpoint}/${req.params.id}`, data: null, error: err, status: 502 }); } else{ return res.status(200).json({ method: 'DELETE', route: `/api/${req.params.endpoint}/${req.params.id}`, data: deletedDocument, error: null, status: 200 }); }; }); }); ``` <br> ## Factorisation du CRUD Nous venons de définir toute les routes pour gérer des articles dans notre API mais il est posssible d'uiliser ces mêmes routes pour d'autre type d'information. Dans la meesur ou chaque méthode intègrent le paramêtre `endpoint`, il est possible d'ajouteer une condition qui selon sa valeur exécute un code différent : ```javascript= router.put('/:endpoint/:id', (req, res) => { // Check endpoint if(req.params.endpoint === 'post'){ // Specific code for post data ... } else if(req.params.endpoint === 'comment'){ // Specific code for comment data ... } }) ``` Le CRUD que nous venons de mettre en place peut être utilisé dans un très grand nombre de type d'information mais il est à noter que pour les informations sur un utilisteur par exemple ou toutes autres données sensible, il est recommender de créer des routers spécifiques. Dans ces cas la, il faut créer un nouveeau routeur sur la base du fichier `crud.router.js` et coonfigurer la route correspondante dans le fichie `server.js` : ```javascript= // Set AUTH router const AuthRouterClass = require('./routers/auth.router'); const authRouter = new AuthRouterClass(); server.use('/api/auth', authRouter.init()); // Set CRUD router const CrudRouterClass = require('./routers/crud.router'); const crudRouter = new CrudRouterClass(); server.use('/api', crudRouter.init()); ``` > Ce code est à adapter pour l'utilisation de la base de données MySQL. --- <br><br><br><br><br><br> # Ressources ![](https://i.imgur.com/iFcSll4.jpg) ## Boilerplate Le code présenter dans ce document est disponible sur un répertoire GitHub et la documentation de l'API à été réalisé avec Postman : - **Répertoire GitHub**: https://github.com/DWS-paris/NODEapi_boilerplate - **Documentation PostMan** : https://bit.ly/2LLbiGC <br><br> ## Liens utiles La liste ci-dessous contient les liens utiles cité dans ce document. - [**Interface de programmation** https://fr.wikipedia.org/wiki/Interface_de_programmation](https://fr.wikipedia.org/wiki/Interface_de_programmation) - [**Service web** https://fr.wikipedia.org/wiki/Service_web](https://fr.wikipedia.org/wiki/Service_web) - [**Protocole HTTP** https://fr.wikipedia.org/wiki/Hypertext_Transfer_Protocol](https://fr.wikipedia.org/wiki/Hypertext_Transfer_Protocol) - [**API-First Approach** https://swagger.io/resources/articles/adopting-an-api-first-approach/](https://swagger.io/resources/articles/adopting-an-api-first-approach/) - [**API REST** https://fr.wikipedia.org/wiki/Representational_state_transfer](https://fr.wikipedia.org/wiki/Representational_state_transfer) - [**PHP** https://www.php.net/docs.php](https://www.php.net/docs.php) - [**Javascrypt** https://developer.mozilla.org/en-US/docs/Web/javascript](https://developer.mozilla.org/en-US/docs/Web/javascript) - [**Python** https://www.python.org/doc/](https://www.python.org/doc/) - [**NodeJS** https://nodejs.org/en/](https://nodejs.org/en/) - [**ExpressJS** https://expressjs.com](https://expressjs.com) - [**Machine virtuelle V8** https://fr.wikipedia.org/wiki/V8_(moteur_JavaScript)](https://fr.wikipedia.org/wiki/V8_(moteur_JavaScript)) - [**Libuv** https://en.wikipedia.org/wiki/Libuv](https://en.wikipedia.org/wiki/Libuv) - [**Licence MIT** https://fr.wikipedia.org/wiki/Licence_MIT](https://fr.wikipedia.org/wiki/Licence_MIT) - [**CommonJS** https://fr.wikipedia.org/wiki/CommonJS](https://fr.wikipedia.org/wiki/CommonJS) - [**Ryan Dahl** https://github.com/ry](https://github.com/ry) - [**OpenSource** https://fr.wikipedia.org/wiki/Open_source](https://fr.wikipedia.org/wiki/Open_source) - [**Modules NPM** https://www.npmjs.com](https://www.npmjs.com) - [**Dotenv** https://www.npmjs.com/package/dotenv](https://www.npmjs.com/package/dotenv) - [**Varibables d'environement serveur** https://fr.wikipedia.org/wiki/Variable_d%27environnement](https://fr.wikipedia.org/wiki/Variable_d%27environnement) - [**Classes Javascript** https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Classes](https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Classes) - [**Moteur de rendu** https://fr.wikipedia.org/wiki/Moteur_de_rendu](https://fr.wikipedia.org/wiki/Moteur_de_rendu) - [**Embedded JavaScript** https://www.npmjs.com/package/ejs](https://www.npmjs.com/package/ejs) - [**HTML** https://fr.wikipedia.org/wiki/Hypertext_Markup_Language](https://fr.wikipedia.org/wiki/Hypertext_Markup_Language) - [**Path** https://www.npmjs.com/package/path](https://www.npmjs.com/package/path) - [**CRUD** https://fr.wikipedia.org/wiki/CRUD](https://fr.wikipedia.org/wiki/CRUD) - [**JSON** https://fr.wikipedia.org/wiki/JavaScript_Object_Notation](https://fr.wikipedia.org/wiki/JavaScript_Object_Notation) - [**Base de données NOsql** https://fr.wikipedia.org/wiki/NoSQL](https://fr.wikipedia.org/wiki/NoSQL) - [**MongoDB** https://fr.wikipedia.org/wiki/MongoDB](https://fr.wikipedia.org/wiki/MongoDB) - [**Mongoose** https://www.npmjs.com/package/mongoose](https://www.npmjs.com/package/mongoose) - [**Promise** https://developer.mozilla.org/fr/docs/Web/JavaScript/Guide/Utiliser_les_promesses](https://developer.mozilla.org/fr/docs/Web/JavaScript/Guide/Utiliser_les_promesses) - [**Base de données relationnelles** https://fr.wikipedia.org/wiki/Base_de_données_relationnelle](https://fr.wikipedia.org/wiki/Base_de_données_relationnelle) - [**MySQL** https://fr.wikipedia.org/wiki/MySQL](https://fr.wikipedia.org/wiki/MySQL) - [**Stack LAMP** https://fr.wikipedia.org/wiki/LAMP](https://fr.wikipedia.org/wiki/LAMP) - [**Body Parser** https://www.npmjs.com/package/body-parser](https://www.npmjs.com/package/body-parser)