Vous êtes sur la page 1sur 83

ENI RV NodeJS et ExpressJS p.

________________________________________________________________________________________________
donnée en mémoire tampon. Ces applications
Développement produisent simplement les données en morceaux.
d’applications Web Node.js est la technologie de serveur Web utilisée
avec NodeJS entre autres par les sites de compagnies
comme : Youtube, Yahoo, Amazon, Netflix,
eBay, Reddit,
LinkedIn, Paypal, Groupon ou Walmart.
Partie 1. Qu'est-ce que node.js ?

Node.js est une plateforme multiplateforme basée Installer Node.js


sur le moteur d’exécution de Chrome (V8 Engine)
permettant de créer facilement des applications
Node.js est téléchargeable sur NodeJS.org à
réseau et d'éxécuter du code JavaScript du côté
l’adresse: https://nodejs.org
serveur. Node.js utilise un modèle d'E / S non
bloquant, basé sur les événements, ce qui lui
permet de gérer plusieurs tâches de façon Le package Node.js inclut également l'outil NPM
asynchrone. Le package Node.js inclut également (Node Package Manager : gestionnaire de
l'outil NPM (Node Package Manager) qui permet dépendances ) qui permet le téléchargement des
le téléchargement des dépendances . dépendances .

Node.js fournit également une riche bibliothèque Après installation , on aura des commandes
de divers modules JavaScript, ce qui simplifie "node" pour exécuter le code javascript et "npm"
grandement le développement d'applications Web pour télécharger les différents moddules.
utilisant Node.js.
# node –v
Node.js = Runtime Environment + JavaScript
Library # npm –v

Caractéristiques de Node.js Le fichier de configuration

• Asynchrone et événementielle - Toutes Package.json (placé à la racine de votre


les API de la bibliothèque Node.js sont projet)
asynchrones, c'est-à-dire non bloquantes. Cela
signifie essentiellement qu'un serveur basé sur Voici un extrait de ce fichier :{
Node.js n'attend jamais qu'une API retourne des
données. Le serveur passe à la prochaine API "name": "firstapp", // nom app
après l'avoir appelée et un mécanisme de "version": "0.0.0", // version app
notification des événements de Node.js aide le "dependencies": {},
serveur à obtenir une réponse du précédent appel "devDependencies": {
d'API. "grunt": "^0.4.1",
"grunt-autoprefixer": "^0.7.3",
• Très rapide - Construite sur le moteur "grunt-concurrent": "^0.5.0",
JavaScript V8 de Google Chrome, la bibliothèque ...
Node.js est très rapide en exécution de code. "grunt-wiredep": "^1.7.0",
"jshint-stylish": "^0.2.0",
• Single Threaded : Node.js utilise un seul "load-grunt-tasks": "^0.4.0",
programme threadé et le même programme peut "time-grunt": "^0.3.1"
fournir des services à un nombre beaucoup plus },
"engines": {
grand de requêtes que des serveurs traditionnels
"node": ">=0.10.0"
tels qu'Apache HTTP Server (Le serveut }
multithread ). }

• Pas de mise en mémoire tampon - Les Il s'agit du fichier de configuration utilisé par npm
applications Node.js ne mettent jamais aucune pour décrire notre application. On y retrouve
ENI RV NodeJS et ExpressJS p.2

________________________________________________________________________________________________
notamment le nom et la version courante de notre Tous les modules node sont installés dans le
application. On retrouve également les répertoire node_modules et sont décrits dans
dépendances nécessaires au bon fonctionnement vos dépendances du fichier package.json.
de notre application.
Pour desiinstaller un module : npm uninstall
Remarquez que l'on a deux champs qui nom_module
permettent de décrire les dépendances :
Historique du Javascript
• le champ "dependencies"
• le champ "devDependencies"

Le champ "dependencies" décrit les dépendences Les 3 vies de JavaScript


nécessaires au fonctionnement du module. Le
champ "devDependencies" décrit les
dépendences nécessaires au développement du
module.

Exemple : admettons que nous souhaitions utiliser


le module express qui est un framework web et le
sauvegarder dans la liste des dépendances. Par
exemple : dans notre projet nous allons donc
saisir la commande suivante :

npm install express –save


npm install nom_module –save : permet
d’ajouter un nouveau package dans le fichier
package.json

Dans ce cas, nous ne voulons pas prendre part au


développement du module express, mais
seulement l'utiliser. De ce fait, la commande
déclenche l'installation de l'ensemble des
dépendances du module express décrites dans le
champ "dependencies" et non
"devDependencies".

Pour installer Express de façon temporaire et ne


pas l’ajouter à la liste des dépendances, omettez
l’option --save :

$ npm install express ((npm install


nom_module )

Dans le champ "engine", on décrit la version de


node nécessaire pour que notre application
fonctionne.

La commande suivante permet d'installer


automatiquement l'ensemble des dépendances
présentes dans les champs "dependencies" et
"devDependencies" ( après modification du fichier Architecture web avec Node.js
package.json).

npm install
ENI RV NodeJS et ExpressJS p.3

________________________________________________________________________________________________

Node.js n'est qu'un interpréteur JavaScript


enrichissant celui-ci avec diverses API (appelées
module) qui permet d'exécuter des fichier .js
(comme des scripts PHP, Ruby, Python...).

Node.js nous permet d'utiliser le langage


JavaScript sur le serveur... Il nous permet donc
de faire du JavaScript en dehors du navigateur !

Node.js : le JavaScript côté serveur


Le schéma classique : PHP sur le serveur,
Jusqu'ici, JavaScript avait toujours été utilisé du JavaScript chez le client
côté du client, c'est-à-dire du côté du visiteur qui
navigue sur notre site. Le navigateur web du Avec l'arrivée de Node.js, on peut toujours utiliser
visiteur (Firefox, Chrome, IE...) exécute le code du JavaScript côté client pour manipuler la page
JavaScript et effectue des actions sur la page HTML.
web.
Par contre, Node.js offre un environnement
côté serveur qui nous permet aussi d'utiliser le
langage JavaScript pour générer des pages web
en remplacement de langages serveur comme
PHP, Java EE, etc.
ENI RV NodeJS et ExpressJS p.4

________________________________________________________________________________________________
comment on écrirait le code dans un modèle
bloquant :

1. Télécharger un fichier
2. Afficher le fichier
3. Faire autre chose

Les actions sont effectuées dans l'ordre. Il faut lire


les lignes de haut en bas :

1. Le programme va télécharger un fichier


sur Internet
2. Le programme affiche le fichier à
l'utilisateur
3. Puis ensuite le programme peut faire
d'autres choses (effectuer d'autres actions)

Maintenant, on peut écrire le même code sur un


modèle non bloquant :

Télécharger un fichier
Dès que c'est terminé, afficher le fichier
Faire autre chose

Le programme n'exécute plus les lignes dans


l'ordre où elles sont écrites. Il fait ceci :

1. Le programme lance le téléchargement


d'un fichier sur Internet
2. Le programme fait d'autres choses (le
programme suit son cours)
3. Dès que le téléchargement est terminé, le
Un seul langage Front-end (du côté client) programme effectue les actions qu'on lui
et Back-end (du côté serveur) : javascript. avait demandées : il affiche le fichier

Pourquoi Node.js est-il rapide ? Schématiquement, l'exécution du programme peut


donc se représenter comme ça :
Node.js tient principalement à deux choses : le
moteur V8 et son fonctionnement non bloquant.

Le moteur V8

Node.js utilise le moteur d'exécution rapide V8 de


Google Chrome qui effectue la compilation
JIT (Just In Time). Il transforme le code
JavaScript très rapidement en code
machine

Le modèle non bloquant

Modèle bloquant vs modèle non bloquant

Imaginez un programme dont le rôle est de


télécharger un fichier puis de l'afficher. Voici
ENI RV NodeJS et ExpressJS p.5

________________________________________________________________________________________________
var callback = function (error, response, body) {
console.log("Fichier téléchargé !");
});

request('http://www.site.com/fichier.zip', callback);
request('http://www.site.com/autrefichier.zip',
callback);

Si le modèle avait été bloquant, le programme


aurait :

1. Lancé le téléchargement du fichier 1, et


attendu qu'il se termine...
2. ... puis lancé le téléchargement du fichier
2, et attendu qu'il se termine.

Or, avec Node.js, les deux téléchargements sont


lancés en même temps ! Le programme n'attend
pas la fin du premier téléchargement pour passer
à l'instruction suivante.

Le modèle non bloquant en programmation Du coup, le téléchargement des 2 fichiers au total


avec Node.js va beaucoup plus vite puisque le programme fait
les 2 à la fois :
Voici un exemple de programme Node.js qui
télécharge un fichier sur Internet et affiche "Fichier
téléchargé !" quand il a terminé :

request('http://www.site.com/fichier.zip', function
(error, response, body) {
console.log("Fichier téléchargé !");
});
console.log("Je fais d'autres choses en
attendant...");

La requête de téléchargement est lancée en


premier. Ensuite, le programme fait d'autres
choses (ici, il affiche un message dans la
console). Dès que le téléchargement est terminé,
le programme va à la ligne 2 en appelant une
fonction de callback qui effectue des actions et
affiche "Fichier téléchargé !".

// Résultat identique au code précédent

var callback = function (error, response, body) {


console.log("Fichier téléchargé !");
});

request('http://www.site.com/fichier.zip', callback);
console.log("Je fais d'autres choses en
attendant...");

Exemple 2 de modèle non bloquant : Imaginez


qu'on demande le téléchargement de 2 fichiers à
Node.js :
ENI RV NodeJS et ExpressJS p.6

________________________________________________________________________________________________
serveur un thread se charge de la gérer, et
il n’est libéré qu’une fois que les opérations
demandées par la requête en question
sont achevées, le thread est donc bloqué.

En modèle non bloquant (comme Node.js), les 2


fichiers sont téléchargés en même temps et Comme plusieurs visiteurs peuvent demander une
l'ensemble finit plus vite page en même temps au serveur, le serveur
Apache se charge de les répartir et de les
exécuter en parallèle dans des threads différents.
Dans les applications web, il est courant d'avoir
Chaque thread utilise un processeur différent sur
des opérations longues et bloquantes comme : le serveur (ou un noyau de processeur) :

• Les appels aux bases de données


• Les appels à des services web (ex : l'API
de Twitter)

Node.js nous évite de perdre du temps en nous


permettant de faire d'autres choses en attendant
que les actions longues soient terminées !

Des serveurs web et des threads

Les plates-formes web traditionnelles telles que


PHP, Java ou .Net- utilisent en général un
système de multi-threading (plusieurs
thread en parallèles) pour gérer la
concurrence, pour chaque requête au
ENI RV NodeJS et ExpressJS p.7

________________________________________________________________________________________________

Le serveur Apache est multithread

Avec Node.js, on n'utilise pas de serveur web Exécuter un script


HTTP comme Apache. En fait, c'est à nous de
créer le serveur . Node.js est monothread, Le plus simple pour utiliser Node.js est de
contrairement à Apache. Cela veut dire qu'il n'y a l'appeler avec un fichier .js en paramère.
qu'un seul processus, qu'une seule version du
programme qui peut tourner à la fois en mémoire. Pour lancer son exécution , tapez dans la console

node monfichier.js

Par exemple avec monfichier.js qui contient cette


boucle de calcul et qui affiche le temps
nécessaires pour la terminer :

/* Script de benchmark simpliste pour CPU */

var nb=5000000;

var t1=new Date();

var somme=0;
ENI RV NodeJS et ExpressJS p.8

________________________________________________________________________________________________
for (var i=0; i<nb; i++) { dossier appelé "node_modules". C'est une
convention de Node.js :
somme+=Math.cos(i);
var test = require('test'); // Fait appel à test.js
} (sous-dossier node_modules)

var t2=new Date(); En résumé :

var ms=t2.getTime()-t1.getTime();

console.log("Temps de la boucle pour "+nb+"


itérations : "+ms+" ms");

On obtient dans la console :

Temps de la boucle pour 5000000 itérations :


1730 ms;

Création des modules personnalisés

Node.js possède des modules intégrés: par


exemple le module http pour créer un
serveur http, le module "url".

var http = require('http'); // nodejs fait appel au


fichier http.js
var url = require('url'); // nodejs recherche le fichier
url.js

Afin d'organiser votre code (découper votre


projet en plusieurs petits fichiers) , il est
possible de créer des modules
personnalisés avec Node.js pour réutiliser
un groupe de fonctions dans plusieurs
fichiers.

Les modules sont donc de simples fichiers .js. Si


on veut créer un module "test", on doit créer un
fichier test.js dans le même dossier et y faire
Création d’un module
appel comme ceci :
Créez un fichier monModule.js comportant une
var test = require('./test'); // Fait appel à test.js
fonction "exportée" :
(même dossier)
monModule.js
Il ne faut pas mettre l'extension .js dans le
require()!
function fonctionTresUtile() {
Si le module se trouve dans le dossier parent,
nous pouvons l'inclure comme ceci : console.log("Ceci s'affiche depuis une fonction
exportée de monModule.js !");
var test = require('../test'); // Fait appel à test.js
(dossier parent) }

Pour éviter d’utiliser du chemin relatif , il faut console.log permet d’afficher du texte sur la
mettre votre fichier test.js dans un sous- console « serveur ».
ENI RV NodeJS et ExpressJS p.9

________________________________________________________________________________________________
function bonjour( nom) { // Permet l'accès aux fonctions définies dans
monModule.js
console.log("Bonjour "+nom);
// Notez que le ./ est indispensable
}
monModule.fonctionTresUtile();
//monModule.f1();

exports.fonctionTresUtile = fonctionTresUtile; monModule.bonjour("rabe");//monModule.f2("r


abe");
// exports.f1 = fonctionTresUtile;

exports.bonjour = bonjour;

// exports.f2= bonjour;

On peut faire directement :

exports.bonjour = function() { ... };

exports.somme = function(x,y){
return x+y ;
}) ;

exports.somme= (x,y) => (x+y) ; // simplifier les


écritures de fonctions

Les 2 déclarations suivantes sont Exportation d'une fonction


équivanlentes :
// exécute la fonction exportée
exports.nomfonction =
function(par1,para2,..,parn) { code... }; Lancer application.js : node application.js
exports.nomfonction = (par1,para2,..,parn) => {
... };
Réponse :

Ceci s'affiche depuis une fonction exportée de


exports permet d'exporter des objets si le fichier
monModule.js !");
est appelé comme un module, avec require.
Bonjour rabe
On exporte les fonctions pour qu'elles soient
utilisables de l'extérieur
Exemple 2 d’un module cercle.js :
Dans le même répertoire, créez un fichier const PI = 3.14159;
application.js contenant :
exports.aire = (r) => PI * r * r;
application.js
exports.circonference = (r) => 2 * PI * r;
const monModule = require('./monModule'); //
Dans mon fichier test.js :
inclusion
const moncercle = require('./cercle.js'); //appel de
// var monmodule = require('./monmodule'); module
ENI RV NodeJS et ExpressJS p.10

________________________________________________________________________________________________
console.log('L\'aire d\'un cercle de rayon 4 est $ Pour l'installer globalement le module vue cli , on
{moncercle.aire(4)}'); // appel de fonction du va ajouter le paramètre -g à la commande npm :
module

console.log("La circonference d'un cercle de npm install -g @vue/cli


rayon 4 est "+moncercle.circonference(4)); // idem

On remarque plusieurs choses : Vous aurez alors accès à un exécutable vue


dans votre console :
- Le fichier utilisé comme bibliothèque doit mettre
à disposition une ou des fonctions (méthodes) en $ vue create projet-vue.
utilisant « exports ».
Les modules installés globalement ne peuvent
- Le fichier qui exploite la bibliothèque fait un pas être inclus dans vos projets
« require » avec « ./ » pour désigner Node.js avec require()!
l’emplacement du fichier à appeler (ici les deux
fichiers sont dans le même dossier). var module = require('nommodule');
- le « require » est assigné à une constante (ou
une variable) dont on pourra ensuite appeler les
méthodes comme membre (ici les fonctions
« aire » et « circonference »). Mettre à jour les modules

Avec une simple commande :

Installation d’un module npm update ou npm install

Pour installer localement un module, placez- ... NPM va chercher sur les serveurs s'il y a de
vous dans le dossier de votre projet et tapez : nouvelles versions des modules, puis mettre à
jour les modules installés sur votre machine et il
npm install nomdumodule supprimera les anciennes versions.

NPM va télécharger automatiquement la dernière npm install peut être utilisé après avoir modifié le
version du module et il va la placer dans fichier package.json
un sous-dossier node_modules.
Par exemple :
npm install express
{
var express = require ( 'express' ) ; // utilise le "name": "mon-app",
module express dans l’application "version": "0.1.0",
"dependencies": {
Pour desinstaller , "markdown": "~0.4"
npm uninstall nomdumodule }
}

L'installation locale et l'installation globale


Déclarer son module
NPM installe les modules localement pour chaque
Les modules externes d’une application peuvent
projet. C'est pour cela qu'il crée un sous-dossier
évoluent de version en version et votre
node_modules à l'intérieur de votre projet.
programme pourrait devenir incompatible suite à
Si vous utilisez le même module dans 3 projets
une mise à jour d'un module externe. On peut
différents, il sera téléchargé et copié 3 fois. Par
définir les dépendances du programme en créant
contre, il faut savoir que NPM permet aussi
un simple fichier JSON package.json dans le
d'installer des modules globaux. Cela ne sert que
même dossier que votre application. Par
dans de rares cas où le module fournit des
exemple :
exécutables (et pas juste des fichiers .js).
ENI RV NodeJS et ExpressJS p.11

________________________________________________________________________________________________
{
"name": "mon-app",
"version": "0.1.0",
"dependencies": {
"markdown": "~0.4"
}
}

Ce fichier JSON contient 3 paires clé-valeur :

• name : c'est le nom de votre application.


• version : c'est le numéro de version de
votre application. Il est composé d'un
numéro de version majeure, de version
mineure et de patch
• dependencies : c'est un tableau listant les
noms des modules dont a besoin votre
application pour fonctionner ainsi que les
versions compatibles. Les numéros de version d'une application Node.js
Le fonctionnement des numéros de version
Par exemple, on peut commencer à numéroter
une application à la version 0.1.0.
Pour bien gérer les dépendances et savoir mettre
à jour le numéro de version de son application, il • Si on corrige un bug, l'application passera
faut savoir comment fonctionnent les numéros de à la version 0.1.1 et il faudra mettre à jour
version avec Node.js. Il y a pour chaque ce numéro dans le fichier packages.json.
application : • Si on améliore significativement
l’application, elle passera à la version
• Un numéro de version majeure. En 0.2.0, puis 0.3.0 et ainsi de suite.
général on commence à 0 tant que • Le jour où on considère qu'elle a atteint un
l'application n'est pas considérée comme jalon important, et qu'elle est mature, on
mature. Ce numéro change très rarement, pourra la passer en version 1.0.0.
uniquement quand l'application a subi des
changements très profonds.
La gestion des versions des dépendances
• Un numéro de version mineure. Ce
numéro est changé à chaque fois que
l'application est un peu modifiée. C'est à vous d'indiquer avec quelles versions de
• Un numéro de patch. Ce numéro est ses dépendances votre application fonctionne. Si
changé à chaque petite correction de bug votre application dépend du module markdown
ou de faille. Les fonctionnalités de v0.3.5 très précisément, vous écrirez :
l'application restent les mêmes entre les
patchs, il s'agit surtout d'optimisations et "dependencies": {
de corrections indispensables. "markdown": "0.3.5" // Version 0.3.5
uniquement
}

Si vous faites un npm update pour mettre à jour


les modules externes, markdown ne sera jamais
mis à jour (même si l'application passe en version
0.3.6). Vous pouvez mettre un tilde devant le
numéro de version pour autoriser les mises à jour
jusqu'à la prochaine version mineure :

"dependencies": {
"markdown": "~0.3.5" // OK pour les versions
0.3.5, 0.3.6, 0.3.7, etc. jusqu'à la version 0.4.0
non incluse
ENI RV NodeJS et ExpressJS p.12

________________________________________________________________________________________________
} La fonction de callback est donc appelée à
chaque fois qu'un visiteur se connecte à notre
Si vous voulez, vous pouvez ne pas indiquer de site. Elle prend 2 paramètres :
numéro de patch. Dans ce cas, les modules
seront mis à jour même si l'application change de • La requête du visiteur (req) : cet objet
version mineure : contient toutes les informations sur ce que
le visiteur a demandé. On y trouve le nom
"dependencies": { de la page appelée, les paramètres, les
"markdown": "~0.3" // OK pour les versions éventuels champs de formulaires remplis...
0.3.X, 0.4.X, 0.5.X jusqu'à la version 1.0.0 non • La réponse à renvoyer au client (res) :
incluse c'est cet objet qu'il faut remplir pour donner
} un retour au visiteur. L’objet response
contiendra en général le code HTML de la
Attention néanmoins : entre deux versions page à renvoyer au client par le callback.
mineures, un module peut changer suffisamment
et votre application pourrait être incompatible. On
recommande d'accepter uniquement les mises à
jour de patch, c'est le plus sûr. Tester le serveur HTTP

dans la console , tapez :

Construire un serveur http avec les modules node serveur.js


internes de Node.js :
Ouvrez un navigateur et tapez l'adresse
Créer un fichier serveur.js http://localhost:8080. Vous allez vous connecter
sur votre propre machine sur le port 8080 sur
// require un module Node.js "http" qui permet de lequel votre programme Node.js est en train
créer un serveur web d'écouter !
// La variable http représente un objet JavaScript
qui va nous permettre de lancer un serveur web.
// On appelle la fonction createServer() contenue
dans l'objet http et on enregistre ce serveur dans
la variable server.
// la méthode createServer() comprend en
paramètre la fonction à exécuter quand un visiteur
se connecte à notre site

var http = require('http');


var server = http.createServer(function(req, res) {
res.writeHead(200); // renvoie le code 200 dans
l'en-tête de la réponse, "OK " au navigateur
res.end('Salut tout le monde !'); // termine la
réponse (du texte brut)
});
server.listen(8080); // le serveur est lancé et
"écoute" sur le port 8080

La fonction à exécuter est la fonction de callback.


Pour arrêter votre serveur Node.js, retournez dans
la console et faites Ctrl + C pour couper la
// Code identique au précédent commande.
var fonctioncallback = function(req, res) {
Exemple2
res.writeHead(200);
res.end('Salut tout le monde !');
} const http = require("http");

var server = http.createServer(fonctioncallback);


ENI RV NodeJS et ExpressJS p.13

________________________________________________________________________________________________
// http est un objet qui porte les définies dans le Mozilla/5.0 (Windows NT 5.1; rv:52.0)
module http Gecko/20100101 Firefox/52.0

// Notez qu'il n'y a pas de ./ pour les modules


internes
Retourner du code HTML

Un serveur peut renvoyer différents types de


// Création du serveur données :

const server = http.createServer((requete, result) • Du texte brut : text/plain


=> { • Du HTML : text/html
• Du CSS : text/css
result.statusCode = 200; • Une image JPEG : image/jpeg
• Une vidéo MPEG4 : video/mp4
result.setHeader("Content-Type", "text/html"); • Un fichier ZIP : application/zip
• etc.
result.end("Bonjour depuis Node.js !");
Nous devons rajouter un paramètre qui indique le
console.log(requete.method+" "+requete.url); type MIME de la réponse. Pour HTML, ce sera
donc :
console.log(" "+requete.headers['user-agent']);
res.writeHead(200, {"Content-Type":
}); "text/html"});
// res.setHeader('Content-Type', 'text/plain');

Nous pouvons renvoyer du HTML dans la réponse


// Déclaration de l'ip et du port de notre serveur
!
web
res.end('<p>Voici un paragraphe
const hostname = '127.0.0.1';
<strong>HTML</strong> !</p>');
const port = 3000; Nouveau code :

var http = require('http');

// Lancement de l'écoute du serveur var server = http.createServer(function(req, res) {


res.writeHead(200, {"Content-Type":
server.listen(port, hostname, () => { "text/html"});
res.end('<p>Voici un paragraphe
console.log(`Serveur web lancé à l'adresse <strong>HTML</strong> !</p>');
http://${hostname}:${port}/`); });
server.listen(8080);
});
Un paragraphe HTML renvoyé par notre appli
Dans un navigateur, l'adresse
http://127.0.0.1:3000/ retourne "Bonjour Node.js
depuis Node.js !".

Dans le console :

Serveur web lancé à l'adresse


http://127.0.0.1:3000)

GET /
ENI RV NodeJS et ExpressJS p.14

________________________________________________________________________________________________
var http = require('http') ;
var url = require('url') ;

//var monServeur=function(requete, reponse){

var monServeur=(requete, reponse) =>{

var page = url.parse(requete.url).pathname ;


reponse.writeHead(200,{"Content-Type":
"text/plain; charset=UTF-8"}) ;
On peut utiliser la commande res.write() qui //D'autres reponse.write...
permet d'écrire la réponse en plusieurs temps. switch(page)
res.end() doit toujours être appelé en dernier pour case '/page1' : (…)break ;
terminer la réponse et faire en sorte que le case '/page2' : (…)break ;
serveur envoie le résultat au client case '/page3' : (…)break ;
default : reponse.end('Ce cas ne devrait pas
var http = require('http'); arriver') ;
}
var server = http.createServer(function(req, res) {
res.writeHead(200, {"Content-Type": var serveur = http.createServer(monServeur) ;
"text/html"});
res.write('<!DOCTYPE html>'+ serveur.listen(8888) ;
'<html>'+
' <head>'+ reponse.end est une méthode qui permet de
' <meta charset="utf-8" />'+ publier des données, et qui signale également la
' <title>Ma page Node.js !</title>'+ fin de l'envoi de ces données. Si le volume de
' </head>'+ données est important, il est préférable de passer
' <body>'+ par des reponse.write(donnees), qui peuvent être
' <p>Voici un paragraphe successifs, avant de conclure par
<strong>HTML</strong> !</p>'+ un reponse.end pour terminer la publication. Par
' </body>'+ exemple…
'</html>');
res.end(); reponse.write("<p>Ceci est un
}); paragraphe</p><ul><li>premier item (...)") ;
server.listen(8080); reponse.write("<p>Ceci est un autre
paragraphe</p><ul><li>autre liste (...)") ;
Réponse : Voici un paragraphe HTML ! reponse.end("</body></html>") ;

b. Routage HTTP de base avec Node.js

Le routage consiste à établir des associations Exemple 2 : lire et afficher 3 fichiers HTML.
entre des URL et des contenus que le serveur doit ( indexhtml, about.html, contact.html ) en
fournir. On va se servir d'une propriété de fonction du paramètre de routage.
l'objet requete, qui va nous permettre de
récupérer des informations sur l'URL. Pour cela, il la fonction fs.createReadStream() est utilisé pour
va falloir importer un autre module de node, le lire le fichier en morceaux de la taille spécifiée.
module url en ajoutant var url = require('url');. On Avec createReadStream,on utilise l’événement
peut alors accéder à l'URL saisie, pipe() qui aide à écrire les données de réponse
dans le navigateur.

index.html

<html>
<head>
<title> Homepage </title>
ENI RV NodeJS et ExpressJS p.15

________________________________________________________________________________________________
</head> response . writeHead ( 200 , { 'Content-
<body> Type' : 'text/html' } ) ;
<h1> Homepage </h1> fs . createReadStream ( 'index.html' ) . pipe (
This is homepage. response ) ;
</body> }
</html> } ) . listen ( 8081 ) ;

propos.html // This prints the message in terminal when you


run "node server.js"
<html> console . log ( 'Server running at port 8081:
<head> http://127.0.0.1:8081' ) ;
<title> About Us </title>
</head> Exécutez la commande suivante:
<body>
<h1> About Us </h1> myapp $ node main.js
This is about page. Server running at port 8081 :
</body> http : //127.0.0.1:8081
</html>
Maintenant, ouvrez votre navigateur et tapez ce
contact.html qui suit dans la barre d'adresse de votre
navigateur:
<html> http://127.0.0.1:8081 pour voir le contenu du
<head> fichier index.html chargé sur votre navigateur.
<title> Contact Us </title> http://127.0.0.1:8081/about affichera le contenu du
</head> fichier about.html.
<body> http://127.0.0.1:8081/contact affichera le contenu
<h1> Contact Us </h1> du fichier contact.html.
This is contact page. Tous les autres paramètres de l'URL afficheront le
</body> contenu du fichier index.html. Par exemple,
</html> http://127.0.0.1:8081/xyz affichera le contenu du
fichier index.html.
Maintenant, voici notre fichier Nodejs qui crée le
serveur et fait le routage. Appelons-le main.js.
Déterminer la page appelée et les paramètres
main.js
var http = require('http');
var http = require ( 'http' ) ; var server = http.createServer(function(req, res) {
var fs = require ( 'fs' ) ; res.writeHead(200);
res.end('Salut tout le monde !');
http . createServer ( function ( request , });
response ) {
// print the URL in terminal server.listen(8080);
console . log ( 'URL: ' + request.url ) ;
Avec Node.js, l'application renvoie toujours le
if ( request . url == '/about' ) { même message, quelle que soit la page appelée
response . writeHead ( 200 , { 'Content- (http://localhost:8080,
Type' : 'text/html' } ) ; http://localhost:8080/mapage,
// pipe event is used to write response data http://localhost:8080/dossier/autrepage)
fs . createReadStream ( 'about.html' ) . pipe
( response ) ;
Il faut qu'on sache quelle est la page demandée
} else if ( request . url == '/contact' ) {
par le visiteur parmi les différentes pages .
response . writeHead ( 200 , { 'Content-
Type' : 'text/html' } ) ;
fs . createReadStream ( 'contact.html' ) . Nous allons découvrir comment récupérer :
pipe ( response ) ;
} else { • Le nom de la page demandée
(/mapage, /page.html,
/dossier/autrepage...)
ENI RV NodeJS et ExpressJS p.16

________________________________________________________________________________________________
• Les paramètres qui circulent dans l'URL
(ex : http://localhost:8080/mapage? var server = http.createServer(function(req, res) {
nom=dupont&prenom=robert). var page = url.parse(req.url).pathname;
console.log(page);
Quelle est la page demandée par le visiteur ? res.writeHead(200, {"Content-Type":
"text/plain"});
Pour récupérer la page demandée par le visiteur, if (page == '/') {
on va faire appel à un nouveau module de Node res.write('Vous êtes à l\'accueil, que puis-je
appelé "url". On demande son inclusion avec : pour vous ?');
}
else if (page == '/sous-sol') {
var url = require("url");
res.write('Vous êtes dans la cave à vins, ces
bouteilles sont à moi !');
Ensuite, il nous suffit de "parser" la requête du }
visiteur pour obtenir le nom de la page else if (page == '/etage/1/chambre') {
demandée : res.write('Hé ho, c\'est privé ici !');
}
url.parse(req.url).pathname; res.end();
});
Voici un code très simple :: server.listen(8080);

var http = require('http'); N’oubliez pas d’afficher un message d'erreur si le


var url = require('url'); visiteur demande une page inconnue

var server = http.createServer(function(req, res) { Quels sont les paramètres ?


var page = url.parse(req.url).pathname;
console.log(page);
res.writeHead(200, {"Content-Type": Les paramètres sont envoyés à la fin de l'URL,
"text/plain"}); après le chemin du fichier, par exemple :
res.write('Voici la page + page');
res.end(); http://localhost:8080/page?
}); prenom=Robert&nom=Dupont
server.listen(8080);
Pour récupérer cette chaîne URL , il suffit de faire
appel à :
Si on exécute ce script successivement aux
adresses url.parse(req.url).query

http://localhost:8080, Pour récuperer les paramètres , incluez le module


http://localhost:8080/mapage, querystring pour découper au préalable les
http://localhost:8080/dossier/autrepage, différents paramètres:

http://localhost:8080/favicon.ico, var querystring = require('querystring');


http://localhost:8080/ faussepage.html
Vous disposerez d'un tableau de paramètres
on obtient : "params".:
/
/mapage var params =
/dossier/autrepage querystring.parse(url.parse(req.url).query);
/favicon.ico
/faussepage.html Pour récupérer le paramètre "prenom" par
exemple, il suffira d'écrire : params['prenom'].
Pour renvoyer un message différent en fonction
de la page demandée , on peut ecrire : Voici un code complet qui affiche votre prénom et
votre nom:
var http = require('http');
var url = require('url'); var http = require('http');
ENI RV NodeJS et ExpressJS p.17

________________________________________________________________________________________________
var url = require('url'); La partie javascript
var querystring = require('querystring');
Toujours dans le dossier de votre projet, créez un
var server = http.createServer(function(req, res) { fichier mysql.js destiné à intégrer le code
var params = javascript se connectant à la base de données
querystring.parse(url.parse(req.url).query); mysql.
res.writeHead(200, {"Content-Type":
"text/plain"}); Récupérez une instance d’objet mysql depuis le
if ('prenom' in params && 'nom' in params) { module installé :
res.write('Vous vous appelez ' +
params['prenom'] + ' ' + params['nom']); var mysql = require('mysql');
}
else { Créer un objet de connexion (conn) à la base de
res.write('Vous devez bien avoir un prénom données par le biais de l’objet mysql
et un nom, non ?');
}
var conn = mysql.createConnection({
res.end();
host : "localhost",
});
user : "user",
server.listen(8080);
password : "password",
database : "mysqlTest"
Test : tapez dans un navigateur });
http://localhost:8080?
prenom=Robert&nom=Dupont pour voir le prénom
et le nom conn.connect(function(err) {
if (err) throw err;
Réponse : Vous vous appelez Robert Dupont console.log("Connected!");
});
Schéma résumé pour recupérer l'URL et les
paramètres avec Node.js
Extraction des données : première méthode

Pour exécuter une requête sql select et en


extraire le résultat, on utilise la méthode query
de l’objet de connexion mySqlClient qui prend en
paramètres :
– la requête sql à exécuter sous forme d’une
chaine de caractères;
– une fonction anonyme appelée après l’exécution
de la requête.

La fonction anonyme prend en paramètres :


– un objet indicateur d’erreur (error) fixé à true en
cas d’erreur à l’exécution de la requête;
– une hashtable comportant les données extraites
Accès à une base de données mysql depuis à partir de la requête exécutée (results);
un script node.js – le nombre de champs ou colonnes renvoyés par
la requête sql (fields).
Installation du module nodejs mysql
var selectQuery = 'SELECT * FROM client';
Depuis la ligne de commande, placez dans le
dossier de votre projet test et exécutez la con.query(
commande suivante :
selectQuery,
npm install mysql
function select(error, results, fields) {
ce qui génère un dossier node_modules/mysql
ENI RV NodeJS et ExpressJS p.18

________________________________________________________________________________________________
if (error) {
// Afficher toutes les lignes
console.log(error);
sqlQuery.on("result", function(row) {
con.end(); console.log('nom: ' + row.nom);
console.log('ville: ' + row.ville);
return; });

} sqlQuery.on("end", function() {
con.end();
});
if ( results.length > 0 ) {
sqlQuery.on("error", function(error) {
var firstResult = results[ 0 ]; // récuperer le console.log(error);
premier enregistrement });

console.log('codecli: ' + firstResult['codecli']); Création d’une base de données MYSQL

console.log('nom: ' + firstResult['nom']); var mysql = require('mysql');

console.log('ville: ' + firstResult['ville']);


var con = mysql.createConnection({
} else { host: "localhost",
user: "yourusername",
console.log("Pas de données"); password: "yourpassword"
});
}
con.connect(function(err) {
con.end();
if (err) throw err;
}
console.log("Connected!");
);
con.query("CREATE DATABASE mydb",
L’appel de la méthode end sur l’objet de function (err, result) {
connexion con clôt la connexion au serveur
mysql. if (err) throw err;

console.log("Database created");
con.end(function(err) {
// The connection is terminated now }
});
con.destroy(); )

Extraction des données : deuxième méthode }

on utilise pas une fonction callback mais deux );


événements liés à la librairie : l’événement result
déclenché à chaque fois qu’une ligne de la Création d’une table
requête sql est renvoyé, l’événement end
déclenché lorsque l’exécution de la requête est var mysql = require('mysql');
terminée et l’événement error déclenché
lorsqu’une erreur survient. var con = mysql.createConnection({
host: "localhost",
var selectQuery = 'SELECT * FROM client'; user: "yourusername",
password: "yourpassword",
var sqlQuery = con.query(selectQuery);
database: "mydb"
ENI RV NodeJS et ExpressJS p.19

________________________________________________________________________________________________
}); var sql = "INSERT INTO client (name, address)
VALUES ('Company Inc', 'Highway 37')";
con.query(sql, function (err, result) {
con.connect(function(err) {
if (err) throw err; if (err) throw err;
console.log("Connected!");
var sql = "CREATE TABLE client (id INT console.log("1 record inserted");
AUTO_INCREMENT PRIMARY KEY, name
});
VARCHAR(255), address VARCHAR(255))";

// var sql = "DROP TABLE IF EXISTS client; });

Insertion des lignes multiples


con.query(sql, function (err, result) {
if (err) throw err; On utilise un point d’interrogation dans le sql qui
console.log("Table created"); sera remplacé par un tableau de données:
}); INSERT INTO customers (name, address)
}); VALUES ?

con.connect(function(err) {
Mettre à jour la structure d’une table if (err) throw err;
console.log("Connected!");
var sql = "INSERT INTO customers (name,
address) VALUES ?";
con.connect(function(err) { var values = [
['John', 'Highway 71'],
if (err) throw err;
['Peter', 'Lowstreet 4'],
['Amy', 'Apple st 652'],
console.log("Connected!");
['Hannah', 'Mountain 21'],
var sql = "ALTER TABLE client ADD COLUMN ['Michael', 'Valley 345'],
id INT AUTO_INCREMENT PRIMARY KEY"; ['Sandy', 'Ocean blvd 2'],
['Betty', 'Green Grass 1'],
con.query(sql, function (err, result) { ['Richard', 'Sky st 331'],
['Susan', 'One way 98'],
if (err) throw err; ['Vicky', 'Yellow Garden 2'],
['Ben', 'Park Lane 38'],
console.log("Table altered");
['William', 'Central st 954'],
['Chuck', 'Main Road 989'],
});
['Viola', 'Sideway 1633']
}); ];
con.query(sql, [values], function (err, result) {
if (err) throw err;
console.log("Number of records inserted: " +
Insertion d’une ligne result.affectedRows);
});
con.connect(function(err) { });

if (err) throw err; On peut echapper la requite INSERT comme suit::


console.log("Connected!"); var post = {id: 1, title: 'Hello MySQL'};
ENI RV NodeJS et ExpressJS p.20

________________________________________________________________________________________________
var query = connection.query('INSERT INTO { id: 10, name: 'Vicky', address: 'Yellow Garden
posts SET ?', post, function (error, results, fields) { 2'},
if (error) throw error; { id: 11, name: 'Ben', address: 'Park Lane 38'},
// Neat!
{ id: 12, name: 'William', address: 'Central st
});
console.log(query.sql); // INSERT INTO posts 954'},
SET `id` = 1, `title` = 'Hello MySQL' { id: 13, name: 'Chuck', address: 'Main Road
989'},
Selection des lignes { id: 14, name: 'Viola', address: 'Sideway 1633'}
]
Selectionner tous les clients et afficher les objets
resultats: Clause LIMIT

var mysql = require('mysql'); con.connect(function(err) {


if (err) throw err;
var con = mysql.createConnection({ var sql = "SELECT * FROM customers LIMIT 5";
host: "localhost",
var sql = "SELECT * FROM customers LIMIT 5
user: "yourusername",
OFFSET 2";
password: "yourpassword",
// var sql = "SELECT * FROM customers LIMIT
database: "mydb"
2,5";
});
con.query(sql, function (err, result) {
con.connect(function(err) {
if (err) throw err;
if (err) throw err;
console.log(result);
con.query("SELECT * FROM client", function
});
(err, result, fields) {
});
//con.query("SELECT name FROM client",
function (err, result, fields) {

// con.query("SELECT * FROM client WHERE Selection d’une ligne satisfaisant une


address LIKE 'S%'", function (err, result) { condition

// con.query("SELECT * FROM customers var clientId = 'c2';


ORDER BY name DESC", function (err, result) {
var sql = 'SELECT * FROM client WHERE
codecli= ' + con.escape(clientId);
if (err) throw err;
console.log(result); con.query(sql, function(err, results) {
});
}); var firstResult = results[ 0 ];

on obtient console.log('codecli: ' + firstResult['codecli']);

[ console.log('nom: ' + firstResult['nom']);


{ id: 1, name: 'John', address: 'Highway 71'},
{ id: 2, name: 'Peter', address: 'Lowstreet 4'}, console.log('solde: ' + firstResult['solde']);
{ id: 3, name: 'Amy', address: 'Apple st 652'}, con.end();
{ id: 4, name: 'Hannah', address: 'Mountain 21'},
{ id: 5, name: 'Michael', address: 'Valley 345'}, });
{ id: 6, name: 'Sandy', address: 'Ocean blvd 2'},
{ id: 7, name: 'Betty', address: 'Green Grass 1'}, Ou bien on peut utiliser des caractères ?
{ id: 8, name: 'Richard', address: 'Sky st 331'}, représentant des paramètres
{ id: 9, name: 'Susan', address: 'One way 98'},
ENI RV NodeJS et ExpressJS p.21

________________________________________________________________________________________________
var clientId = 'c2'; });
});
con.query('SELECT * FROM client WHERE
codecli= ?', [clientId], function(err, results) { [
{ user: 'John', favorite: 'Chocolate Heaven' },
var firstResult = results[ 0 ]; { user: 'Peter', favorite: 'Chocolate Heaven' },
{ user: 'Amy', favorite: 'Tasty Lemons' }
console.log('codecli: ' + firstResult['codecli']); ]

console.log('nom: ' + firstResult['nom']);

console.log('solde: ' + firstResult['solde']); con.connect(function(err) {


if (err) throw err;
var sql = "SELECT users.name AS user,
products.name AS favorite
}); FROM users
LEFT JOIN products ON users.favorite_product =
products.id”;
Multiple paramètres: con.query(sql, function (err, result) {
if (err) throw err;
var name = 'Amy';
console.log(result);
var adr = 'Mountain 21';
});
var sql = 'SELECT * FROM customers WHERE
});
name = ? OR address = ?';
con.query(sql, [name, adr], function (err, result) { [
if (err) throw err; { user: 'John', favorite: 'Chocolate Heaven' },
console.log(result); { user: 'Peter', favorite: 'Chocolate Heaven' },
}); { user: 'Amy', favorite: 'Tasty Lemons' },
{ user: 'Hannah', favorite: null },
{ user: 'Michael', favorite: null }
]
On peut échapper une requête SELECT avec la
function mysql.escape

var query = "SELECT * FROM posts WHERE con.connect(function(err) {


title=" + mysql.escape("Hello MySQL"); if (err) throw err;
var sql = "SELECT users.name AS user,
console.log(query); // SELECT * FROM posts
WHERE title='Hello MySQL' products.name AS favorite
FROM users
RIGHT JOIN products ON users.favorite_product
Jointure interne et externe = products.id”;

con.connect(function(err) { con.query(sql, function (err, result) {


if (err) throw err; if (err) throw err;
var sql = "SELECT users.name AS user, console.log(result);
products.name AS favorite FROM users JOIN });
products ON users.favorite_product = });
products.id";
con.query(sql, function (err, result) { Modification des lignes
if (err) throw err;
con.connect(function(err) {
console.log(result);
ENI RV NodeJS et ExpressJS p.22

________________________________________________________________________________________________
if (err) throw err; con.end();

var sql = "UPDATE client SET ville = 'toliara' });


WHERE nom = 'rabe'";
});
con.query(sql, function (err, result) {

if (err) throw err;


Partie 2. Le framework Express.js
console.log(result.affectedRows + " record(s)
updated"); Express est une infrastructure d'applications Web
Node.js qui fournit un ensemble robuste de
con.end(); fonctionnalités permettant de développer des
applications Web et mobiles. Voici quelques-unes
}); des principales fonctionnalités d’Express
Framework:
});
• Permet de configurer des middlewares
Multiples parameters pour répondre aux requêtes HTTP.

var clientId=”c2”; • Définit une table de routage utilisée pour


effectuer différentes actions en fonction de la
con.connect(function(err) { méthode HTTP et de l'URL.

if (err) throw err; • Permet de rendre dynamiquement les


pages HTML en fonction de la transmission
var sql = " con.query('UPDATE client SET d'arguments aux modèles
nom = ?, ville = ?, solde = ? WHERE codecli
= ?', ['rabe', 'paris', 1000, clientId], function Installation
(error, results, fields) {
En supposant que Node.js est déjà installé, créez
if (error) throw error; un répertoire pour héberger votre application.

// ...
$ mkdir myapp
}); $ cd myapp

1. Exécutez la commande npm init dans le


terminal pour créera le fichier package.json pour
Suppresion des lignes
votre projet (application)
con.connect(function(err) {
$ npm init
if (err) throw err;

var sql = "DELETE FROM client WHERE nom= Cette commande vous invite à fournir un certain
'jean'"; nombre d’informations, telles que le nom et la
version de votre application. Pour le moment,
con.query(sql, function (err, result) { vous pouvez simplement appuyer sur la touche
RETURN pour accepter les valeurs par défaut, à
if (err) throw err; l’exception de ce qui suit :

console.log("Number of records deleted: " +


result.affectedRows); entry point: (index.js)
ENI RV NodeJS et ExpressJS p.23

________________________________________________________________________________________________
Entrez app.js ou un nom de votre choix pour le Pour installer Express de façon temporaire et ne
fichier principal. Si vous souhaitez que le nom soit pas l’ajouter à la liste des dépendances, omettez
index.js, appuyez sur la touche RETURN pour l’option --save :
accepter le nom de fichier par défaut suggéré.

Exemple : $ npm install express

Press ^ C at any time to quit . Les modules Node.js installés à l’aide de l’option
--save sont ajoutés à la liste des dépendances
name : ( myapp ) dependencies, dans le fichier package.json. Par
version : ( 1.0.0 ) défaut, depuis la version 5.0, npm install
description : Node . js CRUD application using <package-name> ajoute automatiquement le
MySQL module Node.js à la liste des dépendances. Par la
entry point : ( index . js ) suite, l’exécution de npm install dans le
test command : répertoire de l’application installera
git repository : automatiquement les modules présents dans la
keywords : node , crud , mysql liste des dépendances.
author : Mukesh Chapagain
license : ( ISC )

Contenu du package . json : 4.3. Installation et création d’une application


Expresse avec express-generator
{
"name" : "crud-mysql" , Installation :
"version" : "1.0.0" ,
"description" : "Node.js CRUD application using npm install express-generator -g
MySQL" ,
"main" : "index.js" , Pour obtenir toutes les options de cette nouvelle
"scripts" : { commande, taper :
"test" : "echo \"Error: no test specified\" && exit express -h
1" ,
"start": "node app.js" On crée une nouvelle application avec la
commande :
},
"keywords" : [ express --view=ejs monApplication
"node" ,
"crud" ,
"mysql"
Une fois cette commande lancée, express-
],
generator a automatisé la création d’une
"author" : "Mukesh Chapagain" ,
application de base avec toutes les dépendances
"license" : "ISC"
« classiques » utilisées, le « package.json » qui va
}
bien.

Voici (principalement) ce qu’express-generator a


Is this ok ? ( yes ) yes déjà fait pour nous :

2) Installez le module Express Framework avec - Un « package.json » ne contenant


la commande suivante: AUCUN module installé par défaut. Il
faudra donc lancer un NPM INSTALL
Pou installez Express dans le répertoire myapp, avant d’exploiter notre application de base.
et le sauvegarder dans la liste des dépendances.
Par exemple : - Un dossier « routes » qui contient des
sous-fichiers js. Chacun des sous-fichiers
ici s’occupera de sa propre route en get
$ npm install express --save - Un dossier « public » qui contiendra les
fichiers utiles à la page : les images (sous-
dossier « image »), les scripts JavaScript
ENI RV NodeJS et ExpressJS p.24

________________________________________________________________________________________________
du côté client (sous-dossier « javascript »), app . get ( '/' , function ( request , response ) {
et les CSS (sous-dossier « stylesheets »).
response . send ( 'Hello World' ) ; // affiche le
- Le fichier de base app.js est déjà prêt à texte dans le navigateur
fournir un serveur web « vide » de base.

o Il initialise express.js et body- });


parser (ainsi que d’autres modules)
app . listen ( 8081 , function ( ) {
o Il s’appuie sur des sous-
fichiers js dans le dossier console. log ( 'Server running at port 8081:
« routes » pour 2 routes de base : http://127.0.0.1:3000' ) ;
« / » et « /users », ce qui fait un
code mieux structuré. });
o Il enclenche l’usage d’EJS, et
Ou bien
fournit dans le sous-dossier
« views » 2 pages EJS de base.
var server = app.listen(8081, function () {
o Il s’occupe de la gestion du 404
var host = server.address().address;
- Et enfin un dossier « bin » qui contient
un script de démarrage du serveur var port = server.address().port ;
(« www »), qui s’exécute lorsqu’on lance
en ligne de commande : console.log("Example app listening at http://
%s:%s", host, port) ;
npm start

Entre autres, ce script : })

- Gère les erreurs et redirige les


messages d’erreur pour qu’ils
s’affichent dans la page. Le code ci-dessus charge la bibliothèque de
modules express. L'application express démarre
- Gère les ports système, et ouvre le
le serveur et écoute le port 8081 . Pour la
port 3000 (par défaut) et affichera des
demande d'URL racine ('/'), l'application répond
traces détaillées sur la console de
avec le texte Hello World .
l’activité client.
2) Exécutez le node app.js dans votre terminal:
On peut aussi créer une application Express
avec la commznde myapp $ node app.js
ou bien
 express –view=ejs myapp myapp $ npm start pour executer le script :
 cd myapp {"start": node app.js” } défini dans package.json
 npm install
Server running at port 3000 :
http : //127.0.0.1:8071

Exemple d’une application Node.js & Express 3) Maintenant, ouvrez votre navigateur et
naviguez sur http://127.0.0.1:8081 . Vous devriez
1) Créez un nouveau fichier nommé app.js dans pouvoir voir le texte Hello World affiché dans votre
le répertoire myapp navigateur.

App.js

var express = require ( 'express' ) ;

var app = express ( ) ;


ENI RV NodeJS et ExpressJS p.25

________________________________________________________________________________________________
})

• Objet de requête : répresente la requête


HTTP et possède des propriétés pour la chaîne
de requête de requête, les paramètres, le corps,
les en-têtes HTTP, etc.

• Objet de réponse : la réponse HTTP


envoyée par une application Express lorsqu'elle
reçoit une demande HTTP.

Vous pouvez imprimer des objets req et res qui


fournissent de nombreuses informations relatives
aux requêtes et aux réponses HTTP, notamment
les cookies, les sessions, les URL, etc.

Méthodes de réponse

Les méthodes de l’objet de réponse (res) décrites


dans le tableau suivant peuvent envoyer une
Exemple 2 : pour afficher la page html . réponse au client, et mettre fin au cycle de
demande-réponse. Si aucune de ces méthodes
var express =require('express'); n’est appelée par un gestionnaire de routage, la
var fs = require('fs'); demande du client restera bloquée.
var app = express();
Méthode Description
app.get('/',function(req, res) {
res.writeHead(200, {'Content-Type': 'text/html'}); res.download() Vous invite à télécharger un fichier.
fs.readFile('page.html', function (err,data) {
res.end(data); res.end() Met fin au processus de réponse.
});
}); res.json() Envoie une réponse JSON.
app.get('/hello/:name', function(req,res) { Envoie une réponse JSON avec une
res.writeHead(200, {'Content-Type': res.jsonp()
prise en charge JSONP.
'application/json'});
res.end(JSON.stringify({message: 'Hello ' + res.redirect() Redirige une demande.
req.params.name + '!'}));
}); res.render() Génère un modèle de vue.
app.listen(3000); res.send() Envoie une réponse de divers types.
http://127.0.0.1:3000/ dans n’importe quel Envoie une réponse sous forme de
navigateur pour afficher la page html . res.sendFile
flux d’octets.
http://127.0.0.1:3000/ hello/rabe affiche la donnée Définit le code de statut de réponse et
Json {"message":"Hello rabe!"} res.sendStatus() envoie sa représentation sous forme
de chaîne comme corps de réponse.
Demande de réponse

L'application Express utilise une fonction de


rappel dont les paramètres sont des objets de
requête et de réponse . Les routes avec Express
app.get('/', function (req, res) {

// --
ENI RV NodeJS et ExpressJS p.26

________________________________________________________________________________________________
Routes simples avec Express
La fonction suivante permet de définir des
itinéraires dans une application Express -

app.method (chemin d'accès, gestionnaire)


où :

méthode : l’un des verbes HTTP - get, post, put,


delete.

Path : la route à laquelle la demande sera


exécutée.

Le gestionnaire est une fonction de rappel qui


s'exécute lorsqu'un type de demande
correspondant est trouvé sur la route approprié
c.ad. une fonction de callback est appelée quand
quelqu'un demande cette route.

Par exemple,

var express = require('express'); Nous pouvons également avoir plusieurs


méthodes différentes sur le même itinéraire. Par
var app = express(); exemple,

app.get('/hello', function(req, res){ var express = require('express');


res.send("Hello World!");
var app = express();
});
app.get('/hello', function(req, res){
app.listen(3000);
res.send("Hello World!");
Si nous exécutons notre application et que nous
allons à localhost: 3000 / hello , le serveur reçoit });
une demande get à la route "/ hello" , notre
application Express exécute la fonction de rappel
attachée à cette route et envoie "Hello World!".
app.post('/hello', function(req, res){
comme réponse.
res.send("You just called the post method at
'/hello'!\n");

});

app.listen(3000);

Pour tester cette requête, ouvrez votre terminal et


utilisez cURL ou POSTMAN pour exécuter la
requête suivante -

curl -X POST "http://localhost:3000/hello"

Express fournit une méthode spéciale all, qui


traite de tous les types de méthodes http sur une
ENI RV NodeJS et ExpressJS p.27

________________________________________________________________________________________________
route donnée et utilisant la même fonction. Par Enfin, Express permet de gérer des routes
exemple, dynamiques, c'est-à-dire des routes dont
certaines parties sont variables. Pour reprendre
app.all('/test', function(req, res){ l'exemple précédent avec page1, page2 et page3,
on aurait pu écrire…
res.send("HTTP method doesn't have any effect
on this route!"); app.get('/page:num', function(req, res){
res.send('Ceci est la page '+req.params.num) ;
}); }) ;

Voici une application très basique utilisant


Express pour commencer :
On peut écrire autant de routes de cette façon
var express = require('express'); qu'on le souhaite :

var app = express(); app.get('/', function(req, res) {


res.setHeader('Content-Type', 'text/plain');
app.get('/', function(req, res) { res.send('Vous êtes à l\'accueil, que puis-je
res.setHeader('Content-Type', 'text/plain'); pour vous ?');
res.send('Vous êtes à l\'accueil'); });
});
app.get('/sous-sol', function(req, res) {
app.listen(8080); res.setHeader('Content-Type', 'text/plain');
res.send('Vous êtes dans la cave à vins, ces
bouteilles sont à moi !');
Exemple 2 : });

// app.js app.get('/etage/1/chambre', function(req, res) {


res.setHeader('Content-Type', 'text/plain');
var express = require('express') ; res.send('Hé ho, c\'est privé ici !');
var app = express() ; });
var port = 8888 ;
Si vous voulez gérer les erreurs 404, vous devez
app.listen(port, function(){ inclure les lignes suivantes à la fin de votre code
console.log('Le serveur fonctionne sur le port obligatoirement (juste avant app.listen) :
'+port) ;
}) ; // ... Tout le code de gestion des routes (app.get)
se trouve au-dessus

app.get('/', function(req, res){ app.use(function(req, res, next){


res.send('Bonjour tout le monde') ; res.setHeader('Content-Type', 'text/plain');
}) ; res.status(404).send('Page introuvable !');
});
L'avantage de cette méthode get est qu'elle
renvoie à son tour un objet similaire ; les appels app.listen(8080);
peuvent donc être chaînés. Par exemple…
Routes dynamiques
app.get('/page1', function(req, res){
res.send('Ceci est la page 1') ; Express vous permet de gérer des routes
}) dynamiques, c'est-à-dire des routes dont
.get('/page2', function(req, res){ certaines portions peuvent varier. Vous devez
res.send('Ceci est la page 2') ; écrire :nomvariable dans l'URL de la route, ce qui
}) ; aura pour effet de créer un paramètre accessible
.get('/page3', function(req, res){ depuis req.params.nomvariable. Démonstration :
res.send('Ceci est la page 3') ;
}) ; app.get('/etage/:etagenum/chambre', function(req,
res) {
ENI RV NodeJS et ExpressJS p.28

________________________________________________________________________________________________
res.setHeader('Content-Type', 'text/plain'); res.send('Page Listing');
res.end('Vous êtes à la chambre de l\'étage n°'
+ req.params.etagenum); })
});
Il s’agit d’exemples de chemins de routage basés
Cela vous permet de créer de belles URL et vous sur des masques de chaîne.
évite d'avoir à passer par le suffixe ("?
variable=valeur") pour gérer des variables. Ainsi, Ce chemin de routage fait correspondre acd et
toutes les routes suivantes sont valides : abcd.

• /etage/1/chambre
• /etage/2/chambre app.get('/ab?cd', function(req, res) {
• /etage/3/chambre res.send('ab?cd');
• /etage/nawak/chambre });

Routage de base
Ce chemin de routage fait correspondre abcd,
Le routage consiste à déterminer comment une abbcd, abbbcd, etc.
application répond à une demande client
adressée à un point de terminaison particulier, à
savoir un URI (ou chemin) et une méthode de app.get('/ab+cd', function(req, res) {
requête HTTP spécifique (GET, POST, PUT, res.send('ab+cd');
DELETE ou toute autre méthode de demande });
HTTP.).
Ce chemin de routage fait correspondre abcd,
Express prend en charge les méthodes de abxcd, abRABDOMcd, ab123cd, etc.
routage suivantes qui correspondent aux
méthodes HTTP : get, post, put, delete, etc…
app.get('/ab*cd', function(req, res) {
Nous allons étendre notre programme Hello World res.send('ab*cd');
pour traiter davantage de types de requêtes });
HTTP.

var express = require('express');

var app = express(); // This responds a POST request for the


homepage
// This responds with "Hello GET" on the
homepage app.post('/', function (req, res) {

app.get('/', function (req, res) { console.log("Got a POST request for the


homepage");
console.log("Got a GET request for the
homepage"); res.send('Hello POST');

res.send('Hello GET'); })

})

// This responds a GET request for route // This responds a DELETE request for the
/list/user page. /del_user page.

app.get('/list/user', function (req, res) { Ce chemin de routage fera correspondre des


demandes à /del_user.
console.log("Got a GET request for /list_user");
app.delete('/del_user', function (req, res) {
ENI RV NodeJS et ExpressJS p.29

________________________________________________________________________________________________
console.log("Got a DELETE request for
/del_user");

res.send('Hello DELETE');

})

var server = app.listen(8081, function () {

var host = server.address().address

var port = server.address().port

console.log("Example app listening at http://%s:


%s", host, port)

})
Écran montrant à nouveau
http://127.0.0.1:8081/abcdefg
Enregistrez le code ci-dessus dans un fichier
nommé server.js et exécutez-le à l'aide de la
commande suivante.

$ node server.js

Vous verrez la sortie suivante -

Example app listening at http://0.0.0.0:8081

Vous pouvez maintenant essayer différentes


requêtes sur http://127.0.0.1:8081 pour voir la
sortie générée par server.js. Vous trouverez ci-
dessous quelques captures d’écran montrant
différentes réponses pour différentes URL.

Écran montrant à nouveau


http://127.0.0.1:8081/list_user

Gestionnaires de routage

Vous pouvez fournir plusieurs fonctions de rappel


qui se comportent comme des middleware pour
gérer une demande. La seule exception est que
ces fonctions de rappel peuvent faire appel à
next('route') pour ignorer les rappels de route
restants. Vous pouvez utiliser ce mécanisme pour
imposer des conditions préalables sur une route,
ENI RV NodeJS et ExpressJS p.30

________________________________________________________________________________________________
puis passer aux routes suivantes si aucune raison res.send('Hello from C!');
n’est fournie pour traiter la route actuelle. }

Les gestionnaires de route se trouvent sous la app.get('/example/c', [cb0, cb1, cb2]);


forme d’une fonction, d’un tableau de fonctions ou
d’une combinaison des deux, tel qu’indiqué dans
les exemples suivants. Une combinaison de fonctions indépendantes et
des tableaux de fonctions peuvent gérer une
Une fonction de rappel unique peut traiter une route. Par exemple :
route. Par exemple :

var cb0 = function (req, res, next) {


app.get('/example/a', function (req, res) { console.log('CB0');
res.send('Hello from A!'); next();
}); }

var cb1 = function (req, res, next) {


Dans l’exemple suivant, le gestionnaire sera console.log('CB1');
exécuté pour les demandes de “/secret. next();
}

app.get('/example/d', [cb0, cb1], function (req, res,


app.all('/secret', function (req, res, next) {
next) {
console.log('Accessing the secret section ...');
console.log('the response will be sent by the next
next(); // pass control to the next handler
function ...');
});
next();
}, function (req, res) {
res.send('Hello from D!');
});
Plusieurs fonctions de rappel peuvent traiter une
route (n’oubliez pas de spécifier l’objet next). Par
exemple :

app.get('/example/b', function (req, res, next) { Méthode GET


console.log('the response will be sent by the next
function ...'); Voici un exemple simple qui transmet deux
next(); valeurs à l'aide de la méthode HTML FORM GET.
}, function (req, res) { Nous allons utiliser process_get router dans
res.send('Hello from B!'); server.js pour gérer cette entrée.
});
index.htm

Un tableau de fonctions de rappel peut traiter une <html>


route. Par exemple :
<body>

var cb0 = function (req, res, next) { <form action =


console.log('CB0'); "http://127.0.0.1:8081/process_get" method =
next(); "GET">
}
First Name: <input type = "text" name =
var cb1 = function (req, res, next) { "first_name"> <br>
console.log('CB1');
next(); Last Name: <input type = "text" name =
} "last_name">
var cb2 = function (req, res) {
<input type = "submit" value = "Submit">
ENI RV NodeJS et ExpressJS p.31

________________________________________________________________________________________________
</form> })

Accéder au document HTML en utilisant


http://127.0.0.1:8081/index.htm générera le
</body> formulaire suivant –

</html> First Name:

server.js pour gérer les demandes de page Last Name:


d'accueil ainsi que les entrées envoyées par le
formulaire HTML.

var express = require('express'); Vous pouvez maintenant entrer le prénom et le


nom de famille, puis cliquer sur le bouton Envoyer
var app = express(); pour voir le résultat. Le résultat suivant devrait
alors être renvoyé -

{"first_name":"John","last_name":"Paul"}
app.use(express.static('public'));
Méthode POST
app.get('/index.htm', function (req, res) {
Voici un exemple simple qui transmet deux
res.sendFile( __dirname + "/" + "index.htm" ); valeurs à l'aide de la méthode HTML FORM
POST. Nous allons utiliser process_get router
}) dans server.js pour gérer cette entrée.

app.get('/process_get', function (req, res) { index.htm

// Prepare output in JSON format <html>

response = { <body>

first_name:req.query.first_name, <form action =


"http://127.0.0.1:8081/process_post" method =
last_name:req.query.last_name "POST">

}; First Name: <input type = "text" name =


"first_name"> <br>
console.log(response);
Last Name: <input type = "text" name =
"last_name">
res.end(JSON.stringify(response));
<input type = "submit" value = "Submit">
})
</form>

</body>
var server = app.listen(8081, function () {
</html>
var host = server.address().address
server.js pour gérer les requêtes de page
var port = server.address().port
d'accueil ainsi que les entrées envoyées par le
formulaire HTML.
console.log("Example app listening at http://%s:
%s", host, port)
var express = require('express');
ENI RV NodeJS et ExpressJS p.32

________________________________________________________________________________________________
var app = express(); First Name:

var bodyParser = require('body-parser'); // parser Last Name:


le contenu de la requete
Maintenant, vous pouvez entrer le prénom et le
// Create application/x-www-form-urlencoded nom, puis cliquer sur le bouton Soumettre pour
parser voir le résultat suivant:

var urlencodedParser = {"first_name":"John","last_name":"Paul"}


bodyParser.urlencoded({ extended: false }) ;

app.use(express.static('public'));
Express et les middlewares
app.get('/index.htm', function (req, res) {
Express est un framework basé sur le concept de
res.sendFile( __dirname + "/" + "index.htm" ); middlewares qui sont des fonctions ou morceaux
d'application qui rendent chacun un service
}) spécifique. Une application Express n’est qu’une
succession d’appels de fonctions middleware.

Les fonctions de middleware sont des fonctions


app.post('/process_post', urlencodedParser, qui peuvent accéder à l’objet Request (req), l’objet
function (req, res) { response (res) et à la fonction middleware suivant
dans le cycle demande-réponse de l’application.
// Prepare output in JSON format La fonction middleware suivant est couramment
désignée par une variable nommée next.
response = {
Les fonctions middleware effectuent les tâches
first_name:req.body.first_name, suivantes :

last_name:req.body.last_name • Exécuter tout type de code.


• Apporter des modifications aux objets de
}; demande et de réponse.
• Terminer le cycle de demande-réponse.
• Appeler la fonction middleware suivant
console.log(response);
dans la pile.
res.end(JSON.stringify(response));
Si la fonction middleware en cours ne termine pas
le cycle de demande-réponse, elle doit appeler la
}) fonction next() pour transmettre le contrôle à la
fonction middleware suivant. Sinon, la demande
var server = app.listen(8081, function () { restera bloquée.

var host = server.address().address Express propose un ensemble de middlewares


qui communiquent entre eux et fournissent
var port = server.address().port chacun des micro-fonctionnalités, par exemple :

console.log("Example app listening at http://%s: • compression : permet la compression


%s", host, port) gzip de la page pour un envoi plus rapide
au navigateur
}) • cookie-parser : permet de manipuler les
cookies
Accéder au document HTML en utilisant • cookie-session : permet de gérer des
http://127.0.0.1:8081/index.htm générera le informations de session (durant la visite
formulaire suivant - d'un visiteur)
ENI RV NodeJS et ExpressJS p.33

________________________________________________________________________________________________
• serve-static : permet de renvoyer des
fichiers statiques contenus dans un
dossier (images, fichiers à télécharger...)
• serve-favicon : permet de renvoyer la
favicon du site
• csrf : fournit une protection contre les
failles CSRF
• etc.

Tous ces middlewares communiquent entre eux


en se renvoyant jusqu'à 4 paramètres :

• err: les erreurs


• req: la requête du visiteur
• res: la réponse à renvoyer (la page HTML
et les informations d'en-tête)
• next: un callback vers la prochaine
fonction à appeler

Schéma de communication entre les middlewares

Les middlewares communiquent entre eux

Utiliser les middlewares au sein d'Express

On a besoin d’installer les middlewares dont vous


avez besoin avec npm install avant d'exécuter ce
code.

Concrètement, il suffit d'appeler la méthode


app.use() pour utiliser un middleware. Vous
pouvez les chaîner (les appeler les uns à la suite
des autres). Par exemple, vous pouvez faire :

var express = require('express');


var morgan = require('morgan'); // Charge le
middleware de logging
var favicon = require('serve-favicon'); // Charge le
middleware de favicon

var app = express();

app.use(morgan('combined')) // Active le
middleware de logging
.use(express.static(__dirname + '/public')) //
Indique que le dossier /public contient des fichiers
statiques (middleware chargé de base)
.use(favicon(__dirname + '/public/favicon.ico')) //
Active la favicon indiquée
.use(function(req, res){ // Répond enfin
res.send('Hello');
});
ENI RV NodeJS et ExpressJS p.34

________________________________________________________________________________________________
app.listen(8080); Voici un exemple de chargement d’une série de
fonctions middleware sur un point de montage,
Une application Express peut utiliser les types de avec un chemin de montage. Il illustre une sous-
middleware suivants : pile de middleware qui imprime les infos de
demande pour tout type de demande HTTP
• Middleware niveau application adressée au chemin /user/:id.
• Middleware niveau routeur
• Middleware de traitement d’erreurs
• Middleware intégré app.use('/user/:id', function(req, res, next) {
• Middleware tiers console.log('Request URL:', req.originalUrl);
next();
Middleware niveau application }, function (req, res, next) {
console.log('Request Type:', req.method);
Liez le middleware niveau application à une next();
instance de l’objet app object en utilisant les });
fonctions app.use() et app.METHOD(), où
METHOD est la méthode HTTP de la demande
que gère la fonction middleware (par exemple Les gestionnaires de routage vous permettent de
GET, PUT ou POST) en minuscules. définir plusieurs routes pour un chemin. L’exemple
ci-dessous définit deux routes pour les demandes
Cet exemple illustre une fonction middleware sans GET adressées au chemin /user/:id. La deuxième
chemin de montage. La fonction est exécutée à route ne causera aucun problème, mais ne sera
chaque fois que l’application reçoit une demande. jamais appelée puisque la première route boucle
le cycle demande-réponse.

var app = express(); Cet exemple illustre une sous-pile de middleware


qui gère les demandes GET adressées au chemin
app.use(function (req, res, next) { /user/:id.
console.log('Time:', Date.now());
next();
}); app.get('/user/:id', function (req, res, next) {
console.log('ID:', req.params.id);
next();
Cet exemple illustre une fonction middleware }, function (req, res, next) {
montée sur le chemin /user/:id. La fonction est res.send('User Info');
exécutée pour tout type de demande HTTP sur le });
chemin/user/:id.
// handler for the /user/:id path, which prints the
user ID
app.use('/user/:id', function (req, res, next) { app.get('/user/:id', function (req, res, next) {
console.log('Request Type:', req.method); res.end(req.params.id);
next(); });
});
Pour ignorer les fonctions middleware issues
Cet exemple illustre une route et sa fonction de d’une pile de middleware de routeur, appelez
gestionnaire (système de middleware). La fonction next('route') pour passer le contrôle à la prochaine
gère les demandes GET adressées au chemin route. **REMARQUE **: next('route') ne
/user/:id. fonctionnera qu’avec les fonctions middleware qui
ont été chargées via les fonctions app.METHOD()
ou router.METHOD().
app.get('/user/:id', function (req, res, next) {
res.send('USER'); Cet exemple illustre une sous-pile de middleware
}); qui gère les demandes GET adressées au chemin
/user/:id.
ENI RV NodeJS et ExpressJS p.35

________________________________________________________________________________________________
app.get('/user/:id', function (req, res, next) {
// if the user ID is 0, skip to the next route // a middleware sub-stack that handles GET
if (req.params.id == 0) next('route'); requests to the /user/:id path
// otherwise pass the control to the next router.get('/user/:id', function (req, res, next) {
middleware function in this stack // if the user ID is 0, skip to the next router
else next(); // if (req.params.id == 0) next('route');
}, function (req, res, next) { // otherwise pass control to the next middleware
// render a regular page function in this stack
res.render('regular'); else next(); //
}); }, function (req, res, next) {
// render a regular page
// handler for the /user/:id path, which renders a res.render('regular');
special page });
app.get('/user/:id', function (req, res, next) {
res.render('special'); // handler for the /user/:id path, which renders a
}); special page
router.get('/user/:id', function (req, res, next) {
console.log(req.params.id);
Middleware niveau routeur res.render('special');
});
Le middleware niveau routeur fonctionne de la
même manière que le middleware niveau // mount the router on the app
application, à l’exception près qu’il est lié à une app.use('/', router);
instance de express.Router().
Middleware de traitement d'erreurs
var router = express.Router();
Le middleware de traitement d’erreurs comporte
toujours quatre arguments plus particulièrement
Chargez le middleware niveau routeur par le biais avec la signature (err, req, res, next)) :
des fonctions router.use() et router.METHOD().

Le code d’exemple suivant réplique le système de app.use(function(err, req, res, next) {


middleware illustré ci-dessus pour le middleware console.error(err.stack);
niveau application, en utilisant un middleware res.status(500).send('Something broke!');
niveau routeur : });

var app = express(); Middleware intégré


var router = express.Router();
express.static(root, [options])
// a middleware function with no mount path. This
code is executed for every request to the router La seule fonction middleware intégrée dans
router.use(function (req, res, next) { Express est express.static. L’argument root
console.log('Time:', Date.now()); spécifie le répertoire racine à partir duquel servir
next(); les actifs statiques.
});
Vous pouvez avoir plusieurs répertoires statiques
// a middleware sub-stack shows request info for par application :
any type of HTTP request to the /user/:id path
router.use('/user/:id', function(req, res, next) {
console.log('Request URL:', req.originalUrl); app.use(express.static('public'));
next(); app.use(express.static('uploads'));
}, function (req, res, next) { app.use(express.static('files'));
console.log('Request Type:', req.method);
next();
});
Traitement de fichiers statiques
ENI RV NodeJS et ExpressJS p.36

________________________________________________________________________________________________
Express fournit un middleware intégré })
express.static permettant de gérer des
fichiers statiques, tels que des images, Enregistrez le code ci-dessus dans un fichier
CSS, JavaScript, etc. nommé server.js et exécutez-le à l'aide de
la commande suivante.
Il vous suffit simplement de transmettre le nom du
répertoire dans lequel vous conservez vos $ node server.js
actifs statiques, au middleware
express.static pour commencer à servir Ouvrez maintenant
directement les fichiers. Par exemple, si http://127.0.0.1:8081/images/logo.png dans
vous conservez vos images, CSS et n’importe quel navigateur et observez le
JavaScript dans un répertoire nommé résultat suivant.
public, vous pouvez le faire -

app.use(express.static('public'));

Nous allons garder quelques images dans le


sous-répertoire public / images comme suit -

node_modules

server.js

public/

public/images

public/images/logo.png

Modifions l'application "Hello Word" pour ajouter la


fonctionnalité permettant de gérer les
fichiers statiques.
Middleware tiers
var express = require('express');
Utilisez un middleware tiers pour ajouter des
var app = express(); fonctionnalités à des applications Express.

app.use(express.static('public')); Installez le module Node.js pour la fonctionnalité


requise, puis chargez-le dans votre application au
niveau application ou au niveau router.
app.get('/', function (req, res) {
L’exemple suivant illustre l’installation et le
res.send('Hello World');
chargement de la fonction middleware d’analyse
de cookie cookie-parser et imprime tous les
})
cookies envoyés par le client..
var server = app.listen(8081, function () {
cookie-parser - Analyser l'en-tête de cookie et
renseigner req.cookies avec un objet associé aux
var host = server.address().address noms de cookie.

var port = server.address().port


$ npm install cookie-parser

console.log("Example app listening at http://%s: var express = require('express');


%s", host, port) var app = express();
ENI RV NodeJS et ExpressJS p.37

________________________________________________________________________________________________
var cookieParser = require('cookie-parser'); montés. Une instance Router est un middleware
et un système de routage complet . L’exemple
// load the cookie-parsing middleware suivant créé une routeur en tant que module,
app.use(cookieParser()); charge une fonction middleware, définit des routes
et monte le module de routeur sur un chemin dans
l’application principale.
app.get('/', function(req, res) {
Créez un fichier de routage nommé birds.js dans
console.log("Cookies: ", req.cookies) le répertoire app, avec le contenu suivant :

}) birds.js

app.listen(8081) var express = require('express');


var router = express.Router();
D’autres Middleware tiers comme modules
express : // middleware that is specific to this router appelée
à chaque requête
router.use(function timeLog(req, res, next) {
• body-parser - Il s'agit d'un middleware
console.log('Time: ', Date.now());
node.js pour la gestion des données de formulaire
next();
codées JSON, Raw, Text et URL.
});
// define the home page route
• multer - Il s'agit d'un middleware node.js router.get('/', function(req, res) {
pour la gestion de multipart / form-data res.send('Birds home page');
(Téléchargement de fichiers ) });
// define the about route
$ npm install body-parser --save router.get('/about', function(req, res) {
res.send('About birds');
$ npm install multer –save });

//export this router to use in our index.js


app.route()
module.exports = router;
Vous pouvez créer des gestionnaires de routage
sous forme de chaîne pour un chemin de routage
en utilisant app.route().Voici quelques exemples Puis, chargez le module de routage dans
de gestionnaires de chemin de chaînage définis à l’application pour utiliser ce routeur dans notre
l’aide de app.route(). fichier index.js:

index.js:
app.route('/book')
.get(function(req, res) { var birds = require('./birds');
res.send('Get a random book'); ...
}) app.use('/birds', birds);
.post(function(req, res) {
res.send('Add a book');
}) app.listen(3000);
.put(function(req, res) {
res.send('Update the book');
});
La demande /birds affichera le message 'Birds
home page’ et la demande /birds/about le
express.Router message 'About birds', et appeler la fonction
middleware timeLog spécifique à la route.
Utilisez la classe express.Router pour créer des
gestionnaires de route modulaires et pouvant être Routeurs
ENI RV NodeJS et ExpressJS p.38

________________________________________________________________________________________________
Définir les itinéraires comme ci-dessus est très things". Visitez localhost: 3000 / things / et vous
fastidieux à maintenir. Pour séparer les routes de verrez le résultat suivant.
notre fichier index.js principal, nous allons utiliser
Express.Router . Créez un nouveau fichier appelé
things.js et entrez-y le texte suivant.

things.js

var express = require('express');

var router = express.Router();

router.get('/', function(req, res){

res.send('GET route on things.');

});

router.post('/', function(req, res){

res.send('POST route on things.');

});

Utilisation des moteurs de template avec


//export this router to use in our index.js Express
module.exports = router;
Les templates sont en quelque sorte des langages
Maintenant, pour utiliser ce routeur dans notre faciles à écrire qui nous permettent de produire du
fichier index.js , entrez ce qui suit avant l' appel de HTML et d'insérer au milieu du contenu variable.
la fonction app.listen .
PHP lui-même est en fait un langage de template
index.js qui nous permet de faire ceci :

var express = require('Express'); <p> Êtes vous le visiteur n° <?php echo


$visiteurnum; ?></p>
var app = express();
Concrètement, un langage de templates se
var things = require('./things.js'); caractérise par deux fonctions principales :

//both index.js and things.js should be in same • la substitution de variables : remplacer, par
directory exemple « Bonjour #{name} » par
« Bonjour Jean » si la variable name vaut
app.use('/things', things); « Jean » ;
• l'utilisation de structures conditionnelles et
app.listen(3000); de boucles, dépendant notamment des
variables données en paramètre.
L' appel de la fonction app.use sur la route '/
things'' associe le routeur things à cette route. Il existe beaucoup d'autres langages de
Désormais, toutes les demandes de notre templates, comme Twig, Smarty, Haml, JSP,
application concernant les "/ things'' " seront
Jade, EJS...
traitées par notre routeur Things.js. Le "/" route
dans things.js est en fait une sous-route de "/
ENI RV NodeJS et ExpressJS p.39

________________________________________________________________________________________________
Le principe est le suivant : depuis votre fichier
JavaScript, vous appelez le template de votre //Creates a Root Route
choix en lui transmettant les variables dont il a app.get('/',function(req, res){
besoin pour construire la page. res.render('index'); //renders the index.jade file
into html and returns as a response. The render
function optionally takes the data to pass to the
view.
});

//Starts the Express server with a callback


app.listen(PORT, function(err) {
if (!err) {
console.log('Server is running at port', PORT);
} else {
console.log(JSON.stringify(err));
}
});

Pour qu’Express puisse afficher le rendu des


fichiers modèles, vous devez définir les Exemple de template PUG/JADE : index.pug
paramètres d’application suivants : html
head
• views, le répertoire dans lequel se trouvent
les fichiers modèles. Par title= title
exemple : app.set('views', './views') body
• view engine, le moteur de modèle à
utiliser. Par exemple : h1= message

app.set('view engine', 'pug ou jade')


Exemple2 de modèle EJS#
app.set('view engine', 'ejs')
Avec EJS (comme les autres modèles express),
vous pouvez exécuter du code serveur et accéder
à vos variables serveur à partir de votre code
Ensuite, installez le package npm du moteur de HTML.
modèle correspondant :
Syntaxe EJS (Embedded JavaScript templating)
$ npm install ejs pug --save
Ajout des commentaires dans les templates
EJS :

Exemple 1 1. "/* <Comment text> */"

Le code suivant va configurer Jade comme 2. // <Comment text>"


moteur de template.
Dans le code du template, JavaScript
const express = require('express'); //Imports the expressions, HTML, et commentaires sont placés
express module dans des tags speciaux.
const app = express(); //Creates an instance of
the express module
const PORT = 3000; //Randomly chosen port
app.set('view engine','jade'); //Sets jade as the Sujet Tags Description
View Engine / Template Engine
app.set('views','src/views'); //Sets the directory
JavaScript <% (...) Les tags definissent
where all the views (.jade files) are stored.
ENI RV NodeJS et ExpressJS p.40

________________________________________________________________________________________________
« accueil.ejs ». Voici un exemple de fichier
expressions %> JavaScript operations
« accueil.ejs » minimal (page HTML) :
<h1><%= title %></h1> <!DOCTYPE html>
<ul>
<% for(var i=0; <html>
i<produits.length; i++)
{ %> <head>
<li>
<a href='produits /<%= <meta charset="utf-8" />
produits [i] %>'>
<title> TITRE </title>
<%= produits [i] %>
</a> </head>
</li>
<% } %> <body>

<h1> Bonjour et bienvenue à l'Accueil ! </h1>

</body>
HTML-code <%= (...) Les tags
echappent HTML- </html>
%>
constructions
Ensuite, il faut faire appel à cette page dans le
Message:<br>
fichier app.js avec la commande res.render() qui
<input type="text"
va remplacer le res.send :
value="<%= message %>"
name="message" App.js
required>
var express = require('express');

var app = express();


<%- (...) Les tags sortent les
%> informations avec app.set('view engine', 'ejs');
unescaped buffer non
app.get('/', function(req, res) {
échappé
res.render('accueil');
The tags output
information with });
unescaped buffering
//Starts the Express server with a callback

Commentaires <%# (...) Les tags highlight the app.listen(8000) ;


%> comments
Exemple 2 de template EJS

<!-- views/index.ejs -->


Vous pouvez passer des paramètres à l'aide
de res.render('index', {message: message}); (pour
le fichier ejs appelé index.ejs). <html>

<head>

<meta charset="utf-8"/>
Exemple1 Création d’une page en EJS
Par défaut, EJS stocke ses pages dans un sous- <title><%=title%></title>
dossier « views » de votre projet. Donc il faut
commencer par créer ce dossier, puis d’y créer <linkrel="stylesheet"href="/stylesheets/style.c
les pages à l’intérieur, dans un fichier ss"/>
ENI RV NodeJS et ExpressJS p.41

________________________________________________________________________________________________
<p> Voici <%= i%> canard. </p>
</head>
<% } else { %>
<body>
<p> Voici <%= i%> canards. </p>
<h1><%=title%></h1>
<% } %>
<p>Welcome to <%=message%></p>
<% } %>
</body>
</p>
</html>

Passage de paramètres dans les template EJS


depuis URL
Puis, créez une route pour générer le
Prenons par exemple dans notre server.js :
fichier index.ejs. Si la propriété view engine n’est
pas définie, vous devez spécifier l’extension du app.get('/canards/:nbcanards', function(req, res) {
fichier view.
res.render('./pages/canards.ejs',
{qte: req.params.nbcanards});
app.get('/',function(req, res){ });
res.render('index',{ title:'Hey', message:'Hello
there!'}); on peut récupérer le parametre /:nbcanards
( nombre de canards) dans le fichier
}); « canards.ejs » avec le paramètre « qte » comme
cela :
app.listen(8000) ;
canards.ejs

Lorsque vous faites une demande vers la page


d’accueil, le fichier index.ejs est généré en HTML. <!DOCTYPE html >
<html lang="fr">
Dans les balises EJS, vous pouvez également
utiliser if , while ou toute autre commande <head>
javascript souhaitée. <title>Page de test</title>
<meta charset="utf-8" />
</head>

Exemple 1 : <body>
<p> Vous avez <%= qte %> Canards. </p>
<% if (user) { %> </body>

<h2><%= user.name %></h2>


</html>
<% } %>
Exemple 2 :
Exemple 2 : app.get('/etage/:etagenum/chambre', function(req,
res) {
<p> res.render('chambre.ejs', {etage:
req.params.etagenum});
<% for (var i = 1; i <= qte; i++) { %> });
views /chambre.ejs
<% if (i == 1) { %>
ENI RV NodeJS et ExpressJS p.42

________________________________________________________________________________________________
<h1>Vous êtes dans la chambre</h1>

<p>Vous êtes à l'étage n°<%= etage %></p>

Plusieurs paramètres et des boucles

On peut aussi par exemple, réaliser des boucles.


Par exemple…
app.get('/page:num', function(req, res){
res.render('page.ejs', {"numero":
req.params.num}) ;
}) ;
'page.ejs'
<!DOCTYPE html >
<html lang="fr">

<head>
<title>Page de test</title>
<meta charset="utf-8" />
</head>

<body> - Dans « public », les fichiers accessoires qui


<p>Ceci est un paragraphe, sur la page seront envoyés au client : les css, les images et
<%= numero %>.</p> les JavaScript client (comme JQuery par exemple)
<ul>
<% for (let i=0;i<numero;i++){%> - Dans « views », nos templates (fichiers) EJS, en
<li>Ligne <%= 2 catégories :
i+1%></li>
- le dossier « partials » contiendra les
<%}%>
fichiers génériques : les portions communes à
</ul>
toutes nos pages (en-tête, pied de page, menu,
</body>
…),

</html> - et le dossier « pages » contiendra les fichiers


construisant les différentes pages (page d’accueil,
login,

Utilisation du langage Javascript intégré (EJS)


dans une application Node.js & Express
Exemple 1 : créer une application simple Hello
World utilisant EJS
- Installer le module EJS avec la commande
suivante:
Le serveur d'applications écoute le port 3000.
Myapp$ npm install ejs -- save
app.js
l'option -save ajoutera automatiquement la
dépendance du module installé dans le fichier var express = require ( 'express' ) ;
project.json. var app = express ( ) ;

// setting up the templating view engine


Afin de profiter de cette modularité, il est conseillé
app.set ( 'view engine', 'ejs' ) ;
de réorganiser les dossiers d’un projet (Node.js +
app.set('views','src/views');
express.js + EJS) comme suit :
app.get ( '/' , function ( request , response ) {
response . render ( 'index' , { title : 'My
Homepage' , msg : 'Hello World' } ) ;
});
ENI RV NodeJS et ExpressJS p.43

________________________________________________________________________________________________
Il affiche la liste des données du tableau ainsi que
app.listen ( 3000 , function ( ) { les données de chaque élément du
console . log ( 'Server running at port 3000: tableau.
http://127.0.0.1:3000' ) ; Voici le format de travail de l'application.
}); - Le tableau users contient la liste des utilisateurs
avec leur nom d'utilisateur, leur âge et leur
Le modèle HTML pour EJS doit se trouver dans le adresse électronique.
dossier views . Donc, créez un nouveau - Chaque utilisateur est identifié par un ID
dossier nommé "views" puis créez un utilisateur particulier.
nouveau fichier nommé index.ejs dans le - Nous ne montrerons que le nom des utilisateurs
dossier "views". en page d'accueil.
- Nous mettrons un lien "Afficher les détails" à
Nous devons créer le fichier de modèle avec le côté du nom de chaque utilisateur dans la
nom index.ejs car nous avons spécifié liste des utilisateurs de la page d'accueil.
«index» comme nom de fichier dans le - Nous afficherons les détails de chaque utilisateur
code ci-dessus lors du rendu de la (nom, âge, email) sur la page "Afficher les
réponse. détails".

views / index.ejs app.js


var express = require ( 'express' ) ;
< html > var app = express ( ) ;
< head >
< title > <%= title %> < / title > // setting up the templating view engine
< / head > app.set ( 'view engine' , 'ejs' ) ;
< body >
< h1 > <%= title %> < / h1 > // users array
< div > <%= msg %> < / div > var usersList = [
< / body > {
< / html > id : 1 ,
name : 'Mukesh Chapagain' ,
age : 99 ,
email : 'mukesh@example.com'
Dans le code JS, vous pouvez voir que dans la
},
fonction response.render (), nous avons
{
transmis deux variables javascript «title» et
id : 2 ,
«msg» avec quelques valeurs. Ces valeurs
name : 'Brad Pitt' ,
sont transmises au fichier de vue
age : 80 ,
index.ejs. Dans le fichier index.ejs, ces
email : 'brad@example.com'
variables peuvent être imprimées à l'aide
},
de la balise <% =%>.
{
id : 3 ,
Maintenant, allez dans votre dossier de projet et name : 'Steve Smith' ,
exécutez la commande suivante sur le age : 56 ,
terminal / invite de commande: email : 'steve@example.com'
},
Myapp$ node app . js {
Après cela, vous pouvez ouvrir l'URL id : 4 ,
http://127.0.0.1:3000 dans votre navigateur name : 'Darren Sammy' ,
et vous pourrez voir le contenu du fichier age : 48 ,
index.ejs avec le titre et le msg transmis email : 'sammy@example.com'
dans la fonction response.render du fichier }
app.js. ];

app.get ( '/' , function ( request , response ) {


Exemple 2 : Une application Express & EJS response.render ( 'index' , { title : 'My
utilisant des données de tableau Homepage' , msg : 'Hello World' } ) ;
});
ENI RV NodeJS et ExpressJS p.44

________________________________________________________________________________________________
<head >
// for users list page <title> All Users </title>
app.get ( '/users' , function ( request , response ) { </head>
/** <body>
* render to views/users.ejs template file <h1> All Users </h1>
* usersList is set to users variable <div >
*/ <!--
response.render ( 'users' , { users : usersList } ) Using FOREACH LOOP for the users
; array
});
// myArray.forEach( function ( el , index )
// for individual user page {
app.get ( '/user/:id' , function ( request , response ) // el - current element, i - index
{ });
/** -->
* Get the individual user details using request <% users.forEach( function ( user )
param ID { %>
* < p > <%=user.name %> <a
* We use array.filter() function for this purpose href='/user/ <%=user.id %> ' > View
* Details </a> </p>
* filter() is a Javascript function that creates a <% } ) %>
new array with elements </div >
* that satisfies the conditions present in the </body >
callback function </html >
*/ views / user.ejs
var singleUser = usersList.filter ( function ( user <html>
){ <head>
console.log (user.id ) ; return user.id == <title> Single User </title >
request.params.id } ) ; </head >
/** <body >
* The filter creates a new array with single user <h1> User Details </h1 >
element <div>
* Hence, getting the value of the first and only <p> Name : <%=name %> </p>
element <p> Age : <%=age %> </p>
*/ <p> Email : <%=email %> </p>
var singleUser = singleUser [ 0 ] ; </div>
</body>
/** </html>
* render to views/user.ejs template file
* name, age & email variables are passed to Node.js & Express: Routage et application à
the template page unique (SPA)
*/
response . render ( 'user' , { Le code ci-dessous montre un exemple simple
name : singleUser.name , d'utilisation de la fonctionnalité de routage
age : singleUser.age , de base dans Express. La méthode HTTP
email : singleUser.email GET est utilisée pour inclure différents
}); fichiers HTML. Dans la réponse, la
}); méthode sendFile est utilisée pour
transmettre les fichiers HTML au
app.listen ( 3000 , function ( ) { navigateur. Le serveur d'applications
console.log ( 'Server running at port 3000: écoute le port 3000 .
http://127.0.0.1:3000' ) ;
}); app.js

views / users.ejs var express = require ( 'express' ) ;


var app = express ( ) ;
<html >
ENI RV NodeJS et ExpressJS p.45

________________________________________________________________________________________________
app . get ( '/' , function ( request , response ) { <h1> Contact Us </h1>
// This is contact page.
response.send('<h1>Homepage</h1><div </body>
>This is homepage.</div>'); // you can also </html>
directly write HTML content
response . sendFile ( __dirname + '/index.html' Maintenant, allez dans le répertoire de votre projet
); de noeud et exécutez la commande
}); suivante dans terminal / command-prompt:

app . get ( '/about' , function ( request , response ) node app . js


{
response . sendFile ( __dirname + '/about.html' Ensuite, vous pouvez ouvrir les URL suivantes
); dans votre navigateur:
}); http://127.0.0.1:3000 affichera le contenu du
fichier index.html.
app . get ( '/contact' , function ( request , response http://127.0.0.1:3000/about affichera le contenu du
){ fichier about.html.
response . sendFile ( __dirname + http://127.0.0.1:3000/contact affichera le contenu
'/contact.html' ) ; du fichier contact.html.
}); Tous les autres paramètres de l'URL afficheront le
message contenu non trouvé.
app . listen ( 3000 , function ( ) { http://127.0.0.1:8081/xyz affichera le message
console . log ( 'Server running at port 3000: “Cannot GET / xyz”.
http://127.0.0.1:3000' ) ;
});

Voici l'exemple des fichiers index.html , about.html Utilisation des formulaires et récupération des
et contact.html : résultats

index.html Voici un exemple simple de formulaire et de


<html> récupération de ses données SANS l’usage
<head> d’EJS
<title> Homepage </title>
</head> Le module body-parser » est utiilisé pour
<body> récupérer les données issues d’un POST
<h1> Homepage </h1>
This is homepage.
</body>
</html>
propos.html
<html>
<head>
<title> About Us </title>
</head>
<body>
<h1> About Us </h1>
This is about page.
</body>
</html>

contact.html

<html>
<head>
<title> Contact Us </title>
</head>
<body>
ENI RV NodeJS et ExpressJS p.46

________________________________________________________________________________________________
password : 'MonMotDePasse',

database : 'MaBaseDeDonnees'

});

connection.connect(function (err) {

if (err) throw err;

console.log('Vous êtes connecté à votre BDD...');

});

3. Exécution d’une requête SQL


Une fois connecté à la base, il ne nous reste plus
qu’à connaître la syntaxe pour lancer une requête
SQL :

var querystring = 'SELECT type FROM utilisateurs


WHERE login = "'+username+'" AND password =
"'+password+'"';

var query = connection.query(querystring, function


(err, rows, fields) {

if (!err) {

console.log("Ma requête est passée !");

};

});

4. Exploitation des résultats d’une requête SQL


Si l’on lance une requête de SELECT (comme ci-
dessus), on va pouvoir exploiter 3 paramètres :
connection à une Base De Données SQL en
NodeJs : cas de Mysql - err

1. Installation du module mysql ou MariaDB - rows

npm install mysql - fields

« err » dira si l’exécution de la requête s’est bien


2. Connexion à une base
passé (FALSE).
Une fois le module installé, une fois MySQL
(ou MariaDB) actif, votre compte créé et une fois « rows » contiendra tous
votre base de données créée, voici comment s’y les enregistrements résultants de notre SELECT
connecter : si celui-ci s’est bien passé.

var mysql = require('mysql'); « fields » contiendra tous les noms de champ du


résultat de notre SELECT si celui-ci s’est bien
var connection = mysql.createConnection({ passé.

host : 'localhost',

user : 'MonNomDeCompte', var querystring = 'SELECT * FROM utilisateurs;';


ENI RV NodeJS et ExpressJS p.47

________________________________________________________________________________________________
var query = connection.query(querystring, function product_price int ,
(err, rows, fields) {
) ENGINE=INNODB;
if (!err) {

console.log("Ma requête est passée !");

console.log(rows); Structure du projet

console.log(fields);

};

});

Exemple 1 d’application CRUD MySql avec


Express sans validation

Création du projet et installation des modules

Etape 1 : Création du projet

mkdir crud
>Controllers
cd crud
 product
npm init –yes pour initialiser le projet avec le
fichier package.json
index.js
Etape 2 : Installer les modules nécessaires.
//use path module
npm install express -save
const path = require('path');
npm install body-parser –save // pour parse
requête JSON et permettre d’accéder à a //use express module
req.body dans des routes.
const express = require('express');
npm install ejs –save // pour le moteur de
template EJS (Embedded Javascript Templating) //use hbs view engine

npm install mysql –save // pour module mysql //const hbs = require('hbs');

Etape 3: Création de la base et de la table avec const ejs = require('ejs');


express-myconnection
//use bodyParser middleware
create database node_crud_mysql_ejs;
const bodyParser = require('body-parser');
use node_crud_mysql_ejs;
//use mysql database
CREATE TABLE product(
const mysql = require('mysql');
product_id int(11) NOT NULL auto_increment
PRIMARY KEY, var product=require('./controllers/product');

product_name varchar(100) , const app = express();


ENI RV NodeJS et ExpressJS p.48

________________________________________________________________________________________________
/* //app.use('/product',product) ;

//Create connection app.use('/',product) ;

const conn = mysql.createConnection({ /**

host: 'localhost', //route for homepage

user: 'root', app.get('/',(req, res) => {

password: '', let sql = "SELECT * FROM product";

database: 'base' let query = conn.query(sql, (err, results) => {

}); if(err) throw err;

res.render('product_view',{

//connect to database results: results

conn.connect((err) =>{ });

if(err) throw err; });

console.log('Mysql Connected...'); });

});

*/ //route for insert data

//set view engine app.post('/save',(req, res) => {

//app.set('view engine', 'hbs'); let data = {product_name:


req.body.product_name, product_price:
app.set('view engine', 'ejs'); req.body.product_price};

//set views file let sql = "INSERT INTO product SET ?";

//app.set('views',path.join(__dirname,'views')); let query = conn.query(sql, data,(err, results) => {

app.set("views", "./views"); if(err) throw err;

res.redirect('/');

app.use(bodyParser.json()); });

app.use(bodyParser.urlencoded({ extended: });


false}));

//set public folder as static folder for static file


//route for update data
//app.use('/assets',express.static(__dirname +
'/public')); app.post('/update',(req, res) => {

app.use(express.static("public"));
ENI RV NodeJS et ExpressJS p.49

________________________________________________________________________________________________
let sql = "UPDATE product SET
product_name='"+req.body.product_name+"',
product_price='"+req.body.product_price+"' var express=require('express');
WHERE product_id="+req.body.id;
// var app =express();
let query = conn.query(sql, (err, results) => {
const app = express.Router();
if(err) throw err;
const mysql = require('mysql');
res.redirect('/');

});
//Create connection
});
const conn = mysql.createConnection({

host: 'localhost',
//route for delete data
user: 'root',
app.post('/delete',(req, res) => {
password: 'root',
let sql = "DELETE FROM product WHERE
product_id="+req.body.product_id+""; database: 'base'

let query = conn.query(sql, (err, results) => { });

if(err) throwerr;

res.redirect('/'); //connect to database

}); conn.connect((err) =>{

}); if(err) throw err;

**/ console.log('Mysql Connected...');

//server listening });

app.listen(8000, () => {

console.log('Server is running at port 8000'); //route for homepage

}); app.get('/',(req, res) => {

let sql = "SELECT * FROM product_express";

module.exports = app; let query = conn.query(sql, (err, results) => {

if(err) throw err;

Controllers res.render('product_view',{

Product.js results: results

// controller });
ENI RV NodeJS et ExpressJS p.50

________________________________________________________________________________________________
}); let sql = "DELETE FROM product_express
WHERE product_id="+req.body.product_id+"";
});
let query = conn.query(sql, (err, results) => {

if(err) throwerr;

res.redirect('/');
//route for insert data
});
app.post('/save',(req, res) => {
});
let data = {product_name:
req.body.product_name, product_price:
req.body.product_price};
module.exports = app;
let sql = "INSERT INTO product_express SET ?";
views
let query = conn.query(sql, data,(err, results) => {

if(err) throw err;

res.redirect('/');

});

});

//route for update data

app.post('/update',(req, res) => { product_view.ejs

let sql = "UPDATE product_express SET <htmllang="en">


product_name='"+req.body.product_name+"',
product_price='"+req.body.product_price+"' <head>
WHERE product_id="+req.body.id;
<meta charset="utf-8">
let query = conn.query(sql, (err, results) => {
<title>CRUD Node.js and Mysql</title>
if(err) throw err;
<!-- <link href="/assets/css/bootstrap.css"
res.redirect('/'); rel="stylesheet"type="text/css"/>-->

}); <link href="/css/bootstrap.css"


rel="stylesheet"type="text/css"/>
});
</head>

<body>
//route for delete data
<div class="container">
app.post('/delete',(req, res) => {
ENI RV NodeJS et ExpressJS p.51

________________________________________________________________________________________________
<center> <h2>CRUD PRODUCTS WITH </tr>
EXPRESS JS</h2></center>
<%})%>
<button class="btn btn-success" data-
toggle="modal" data-target="#myModalAdd">Add <%}%>
New</button>
</tbody>
<table class="table table-striped" id="mytable">
</table>
<thead>
</div>
<tr>

<th>Product ID</th>
<!-- Modal Add Product-->
<th>Product Name</th>
<form action="/save" method="post">
<th>Price</th>
<div class="modal fade" id="myModalAdd"
<th>Action</th> tabindex="-1" role="dialog" aria-
labelledby="exampleModalLabel" aria-
</tr> hidden="true">

</thead> <div class="modal-dialog"


role="document">
<tbody>
<div class="modal-content">
<% if(results){%>
<div class="modal-header">
<% results.forEach(function(product){%>
<h5 class="modal-title"
<tr> id="exampleModalLabel">Add New Product</h5>

<td><%=product.product_id%></td> <button type="button" class="close"


data-dismiss="modal" aria-label="Close">
<td><%=product.product_name%></td>
<span aria-
<td><%=product.product_price%></td> hidden="true">&times;</span>

</button>

<td> </div>

<a href="javascript:void(0);" class="btn <div class="modal-body">


btn-sm btn-info edit" data-id="<
%=product.product_id%>" data-product_name="< <div class="form-group">
%=product.product_name%>" data-
product_price="<%=product.product_price <input type="text"
%>">Edit</a> name="product_name" class="form-control"
placeholder="Product Name" required>
<a href="javascript:void(0);" class="btn
btn-sm btn-danger delete" data-id="< </div>
%=product.product_id%>">Delete</a>

</td>
ENI RV NodeJS et ExpressJS p.52

________________________________________________________________________________________________
<div class="form-group"> </div>

<input type="text" <div class="modal-body">


name="product_price" class="form-control"
placeholder="Price" required> <div class="form-group">

</div> <input type="text"


name="product_name" class="form-control
</div> product_name" placeholder="Product Name"
required>
<div class="modal-footer">
</div>
<button type="button" class="btn btn-
secondary" data-dismiss="modal">Close</button>

<button type="submit" class="btn btn- <div class="form-group">


primary">Save</button>
<input type="text"
</div> name="product_price" class="form-control price"
placeholder="Price"required>
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
</form>
<input type="hidden" name="id"
class="product_id">

<!-- Modal Update Product--> <button type="button" class="btn btn-


secondary" data-dismiss="modal">Close</button>
<form action="/update" method="post">
<button type="submit" class="btn btn-
<div class="modal fade" id="EditModal" primary">Update</button>
tabindex="-1" role="dialog" aria-
labelledby="exampleModalLabel" aria- </div>
hidden="true">
</div>
<div class="modal-dialog" role="document">
</div>
<div class="modal-content">
</div>
<div class="modal-header">
</form>
<h5 class="modal-title"
id="exampleModalLabel">Edit Product</h5>

<button type="button" class="close" data- <!-- Modal Delete Product-->


dismiss="modal" aria-label="Close">
<form id=" add-row-form" action="/delete"
<span aria- method="post">
hidden="true">&times;</span>

</button>
ENI RV NodeJS et ExpressJS p.53

________________________________________________________________________________________________
<div class="modal fade" id="DeleteModal" $(document).ready(function(){
tabindex="-1" role="dialog" aria-
labelledby="myModalLabel" aria-hidden="true"> //showing data to edit modal

<div class="modal-dialog"> $
('#mytable').on('click','.edit',function(){
<div class="modal-content">
var product_id = $(this).data('id');
<div class="modal-header">
var product_name = $
<h5 class="modal-title" (this).data('product_name');
id="myModalLabel">Delete Product</h5>
var product_price = $
<button type="button" class="close" (this).data('product_price');
data-dismiss="modal" aria-label="Close"><span
aria-hidden="true">&times;</span></button> $('#EditModal').modal('show');

</div> $('.product_name').val(product_name);

<div class="modal-body"> $('.price').val(product_price);

<strong>Are you $('.product_id').val(product_id);


sure to delete this data?</strong>
});
</div>
//showing delete record modal
<div class="modal-footer">
$('#mytable').on('click','.delete',function(){
<input type="hidden"
name="product_id" class="form-control var product_id = $(this).data('id');
product_id2" required>
$('#DeleteModal').modal('show');
<button type="button" class="btn
btn-default" data-dismiss="modal">Close</button> $('.product_id2').val(product_id);

<button type="submit" class="btn });


btn-success">Delete</button>

</div>
});
</div>
</script>
</div>
</body>
</div>
</html>
</form>

product_view.hbs
<script src="/assets/js/jquery.min.js"></script>

<script src="/assets/js/bootstrap.js"></script>
<htmllang="en">
<script>
ENI RV NodeJS et ExpressJS p.54

________________________________________________________________________________________________
<head> <a href="javascript:void(0);" class="btn
btn-sm btn-info edit" data-id="{{ product_id }}"
<meta charset="utf-8"> data-product_name="{{ product_name }}" data-
product_price="{{ product_price }}">Edit</a>
<title>CRUD Node.js and Mysql</title>
<a href="javascript:void(0);" class="btn
<!-- <link href="/assets/css/bootstrap.css" btn-sm btn-danger delete" data-
rel="stylesheet"type="text/css"/>--> id="{{ product_id }}">Delete</a>

<link href="/css/bootstrap.css" </td>


rel="stylesheet"type="text/css"/>
</tr>
</head>
{{/each}}
<body>
</tbody>
<div class="container">
</table>
<h2>Product List</h2>
</div>
<button class="btn btn-success" data-
toggle="modal" data-target="#myModalAdd">Add
New</button>
<!-- Modal Add Product-->
<table class="table table-striped" id="mytable">
<form action="/save" method="post">
<thead>
<div class="modal fade" id="myModalAdd"
<tr> tabindex="-1" role="dialog" aria-
labelledby="exampleModalLabel" aria-
<th>Product ID</th> hidden="true">

<th>Product Name</th> <div class="modal-dialog"


role="document">
<th>Price</th>
<div class="modal-content">
<th>Action</th>
<div class="modal-header">
</tr>
<h5 class="modal-title"
</thead> id="exampleModalLabel">Add New Product</h5>

<tbody> <button type="button" class="close"


data-dismiss="modal" aria-label="Close">
{{#each results}}
<span aria-
<tr> hidden="true">&times;</span>

<td>{{ product_id }}</td> </button>

<td>{{ product_name }}</td> </div>

<td>{{ product_price }}</td> <div class="modal-body">

<td> <div class="form-group">


ENI RV NodeJS et ExpressJS p.55

________________________________________________________________________________________________
<input type="text" <button type="button" class="close" data-
name="product_name" class="form-control" dismiss="modal" aria-label="Close">
placeholder="Product Name" required>
<span aria-
</div> hidden="true">&times;</span>

</button>

<div class="form-group"> </div>

<input type="text" <div class="modal-body">


name="product_price" class="form-control"
placeholder="Price" required> <div class="form-group">

</div> <input type="text"


name="product_name" class="form-control
</div> product_name" placeholder="Product Name"
required>
<div class="modal-footer">
</div>
<button type="button" class="btn btn-
secondary" data-dismiss="modal">Close</button>

<button type="submit" class="btn btn- <div class="form-group">


primary">Save</button>
<input type="text"
</div> name="product_price" class="form-control price"
placeholder="Price"required>
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
</form>
<input type="hidden" name="id"
class="product_id">

<!-- Modal Update Product--> <button type="button" class="btn btn-


secondary" data-dismiss="modal">Close</button>
<form action="/update" method="post">
<button type="submit" class="btn btn-
<div class="modal fade" id="EditModal" primary">Update</button>
tabindex="-1" role="dialog" aria-
labelledby="exampleModalLabel" aria- </div>
hidden="true">
</div>
<div class="modal-dialog" role="document">
</div>
<div class="modal-content">
</div>
<div class="modal-header">
</form>
<h5 class="modal-title"
id="exampleModalLabel">Edit Product</h5>
ENI RV NodeJS et ExpressJS p.56

________________________________________________________________________________________________
<!-- Modal Delete Product--> <script src="/assets/js/jquery.min.js"></script>

<form id=" add-row-form" action="/delete" <script src="/assets/js/bootstrap.js"></script>


method="post">
<script>
<div class="modal fade" id="DeleteModal"
tabindex="-1" role="dialog" aria- $(document).ready(function(){
labelledby="myModalLabel" aria-hidden="true">
//showing data to edit modal
<div class="modal-dialog">
$
<div class="modal-content"> ('#mytable').on('click','.edit',function(){

<div class="modal-header"> var product_id = $(this).data('id');

<h5 class="modal-title" var product_name = $


id="myModalLabel">Delete Product</h5> (this).data('product_name');

<button type="button" class="close" var product_price = $


data-dismiss="modal" aria-label="Close"><span (this).data('product_price');
aria-hidden="true">&times;</span></button>
$('#EditModal').modal('show');
</div>
$('.product_name').val(product_name);
<div class="modal-body">
$('.price').val(product_price);
<strong>Are you
sure to delete this data?</strong> $('.product_id').val(product_id);

</div> });

<div class="modal-footer"> //showing delete record modal

<input type="hidden" $('#mytable').on('click','.delete',function(){


name="product_id" class="form-control
product_id2" required> var product_id = $(this).data('id');

<button type="button" class="btn $('#DeleteModal').modal('show');


btn-default" data-dismiss="modal">Close</button>
$('.product_id2').val(product_id);
<button type="submit" class="btn
btn-success">Delete</button> });
</div>

</div> });
</div> </script>
</div> </body>
</form> </html>

Demarrer le serveur
ENI RV NodeJS et ExpressJS p.57

________________________________________________________________________________________________
node index

Après Save

"Edit Product" modal

Après Edit

Quelques captures d’écran:

Add New Product modal


ENI RV NodeJS et ExpressJS p.58

________________________________________________________________________________________________
Dans le controller user.js , on doit importer API
check pour utiliser les fonctions de validation
Delete avec boite de confirmation : ( Longueur de champ, type mail , type numérique
etc..) .

Liste des fonctions de validation

• isLength()
• isEmail()
• isNumeric()
• contains(), verifie si la valeur contient la
valeur spécifiée
• equals(),verifie si la valeur est équale à la
valeur spécifiée
• isAlpha()
• isAlphanumeric()
• isBoolean()

Validation des données du côte serveur dans • isCurrency()


• isDecimal()
une Template en Nodejs • isEmpty()
• isFloat()
Le module express-validator est un ensemble de
middlewares express.js qui encapsule les • isIn(), verifie si la valeur appartient à une
fonctions validator.js validator et sanitizer.
liste de valeurs
Installation avec Node.js 6 ou plus récent • isInt()
npm install --save express-validator • isJSON()
• isLength()
Exemple de validation d’un formulaire avec
express-validator • isLowercase()
• isNumeric()
register.ejs (Form Register)
• isPostalCode()
<form class="form-group" method="post"
action="/register"> • isURL()
<label for="">Name:</label> • isUppercase()
<input type="text" name="name" value="">
<label for="">email:</label>
<input type="email" name="email" value=""> Pour valider l'entrée et de signaler toute erreur
<label for="">Password:</label> avant de créer l'utilisateur , on a besoin de
<input type="password" name="password" value=""> spécifier les champs à valider comme second
<input type="submit" value="Submit"> argument de la route pour la requete POST /
</form> register

user.js
ENI RV NodeJS et ExpressJS p.59

________________________________________________________________________________________________
const express = require ('express'); const errors = validationResult (req);

const app = express (); if (! errors.isEmpty ()) {

app.use (express.json ()); return res.status (422) .json ({errors:


errors.array ()});
const {check, validationResult} = require
('express-validator'); }

app.post ('/ register ', [ const name = req.body.name

// le nom d'utilisateur doit contenir au moins 3 const email = req.body.email


caractères
const age = req.body.age
check('name').isLength({ min: 3 }),
// ou bien ranger dans un objet json
// on peut combiner
var user={

check('name') name :req.body.name.trim(),


.isAlpha()
email :req.body.email,
.isLength({ min: 10 }) ,
age : req.body.age

}
// on peut personnaliser le message d’erreur avec // ajouter dans la base de données
withMessage():

});
check('name')
.isAlpha()
.withMessage('Must be only alphabetical Chaque fois qu'une demande contenant des
chars') champs de nom d'utilisateur ou de mot de passe
invalides est soumise, le serveur répond comme
.isLength({ min: 10 })
ceci:
.withMessage('Must be at least 10 chars
long') , {

"les erreurs": [{

"emplacement": "corps",
check ('email'). isEmail (),
"msg": "Valeur non valide",
// le mot de passe doit contenir au moins 5
caractères
"param": "nom d'utilisateur"
check ('motdepasse'). isLength ({min: 5}),
}]
check('age').isNumeric()
}
], (req, res) => {

// Recherche les erreurs de validation dans cette


Exemple 2
demande et les enveloppe dans un objet avec des
fonctions pratiques
ENI RV NodeJS et ExpressJS p.60

________________________________________________________________________________________________
user.js
check('email', 'Your email is not

valid').not().isEmpty(),
const express = require ('express');
// check('email', 'Your email is not
const app = express ();
valid').not().isEmpty().isEmail().normalizeEmai

l(),

check('password', 'Your password must be


app.post('/register ', [
at least 5 characters').not().isEmpty(),

check('name').not().isEmpty().withMessage(
// check('password', 'Your password must be
'Name must have more than 5 characters'),
at least 5

characters').not().isEmpty().isLength({min: 5}),
//

check('name').not().isEmpty().isLength({min:
],
5}).withMessage('Name must have more than
function (req, res) {
5 characters'),

const errors = validationResult(req);

console.log(req.body);
check('classYear', 'Class Year should be a

number').not().isEmpty(),
if (!errors.isEmpty()) {

// check('classYear', 'Class Year should be


return res.status(422).jsonp(errors.array());
a number').not().isEmpty().isInt(),
} else {
check('weekday', 'Choose a
res.send({});
weekday').optional(),

}
// check('weekday', 'Choose a

weekday').optional().not().isIn(['Sunday', });

'Saturday']),
ENI RV NodeJS et ExpressJS p.61

________________________________________________________________________________________________

Messages d'erreur personnalisés

Le message d'erreur par défaut de express-


validator est une simple valeur non valide.

Vous pouvez cependant spécifier des messages


d'erreur significatifs de différentes manières.
Cas où check('email', 'Your email is not

valid').not().isEmpty().isEmail().normalizeEmai
Au niveau validateur
l(),
Lorsque vous souhaitez contrôler avec précision
le message d'erreur de chaque validateur, vous
pouvez le spécifier à l'aide de la méthode
.withMessage ().

const {check} = require ('express-validator');

app.post ('/ user', [

// ... quelques autres validations ...

check ('mot de passe').isLength ({min: 5}).


withMessage ('doit contenir au moins 5
caractères')
ENI RV NodeJS et ExpressJS p.62

________________________________________________________________________________________________
.matches (/ \ d /). withMessage ('doit contenir avec le message Le mot de passe doit être
un nombre') composé de 5 caractères et contenir un
nombre, car ces validateurs n'ont pas spécifié
], (req, res) => { un message qui leur est propre.

// Gérer la demande en quelque sorte

}); Exemple 2 d’application CRUD MySql avec


Express avec validation
Dans l'exemple ci-dessus, si le mot de passe
comporte moins de 5 caractères, une erreur avec
Création du projet et installation des modules
le message doit être d'au moins 5 caractères sera
signalée.
Etape 1 : Création du projet
S'il ne contient pas non plus de numéro, une
erreur avec le message doit contenir un numéro mkdir node_crud_mysql_ejs
sera signalée.
cd node_crud_mysql_ejs

npm init –yes pour initialiser le projet avec le


Niveau de champ fichier package.json

Les messages peuvent être spécifiés au niveau Etape 2 : Installer les modules nécessaires.
du champ en utilisant le deuxième paramètre des
middlewares de validation. npm install express -save
Ces messages sont utilisés comme repli lorsqu'un
npm install express-validator -save // utilisé pour
validateur ne spécifie pas son propre message:
validation de formulaire
const {check} = require ('express-validator');
npm install body-parser –save // pour parse
app.post ('/ user', [ requête JSON et permettre d’accéder à a
req.body dans des routes.
// ... quelques autres validations ...
npm install method-override –save // pour passer
check ('mot de passe', 'Le mot de passe doit des données avec les requetes comme PUT et
contenir au moins 5 caractères et contenir un DELETE
nombre')
npm install express-flash-save // utilisé pour
.not (). isIn (['123', 'password', 'god']). afficher des messages après insertion ou
withMessage ('N'utilisez pas un mot commun suppression d’enregistrement.
comme mot de passe')

.isLength ({min: 5})


Les modules cookie-parser et express-session
.matches (/ \ d /) sont utilisés pour stocker les données
temporaires.
], (req, res) => {

// Gérer la demande en quelque sorte npm install cookie-parser –save

}); npm install express-session -save

npm install ejs –save // pour le moteur de


template EJS (Embedded Javascript Templating)

Dans l'exemple ci-dessus, lorsque le champ du npm install mysql –save // pour module mysql
mot de passe est inférieur à 5 caractères ou
ne contient pas de nombre, il sera signalé
ENI RV NodeJS et ExpressJS p.63

________________________________________________________________________________________________
Le module express-myconnection est utilize pour
MySQL connection.

npm install express-myconnection -save

Etape 3: Création de la base et de la table avec


express-myconnection

create database node_crud_mysql_ejs;

use node_crud_mysql_ejs;
Views : Index.ejs, add.ejs , edit.ejs
CREATE TABLE students(

id int(11)NOTNULLauto_increment,

first_name varchar(100)NOTNULL,

last_name varchar(100)NOTNULL,

email varchar(100)NOTNULL, >Controllers


mobile varchar(100)NOTNULL,  students
created_at datetime NOTNULL, App.js

PRIMARY KEY(id) var express=require('express');

); var app=express();

var mysql=require('mysql');

Structure du projet var myConnection =require('express-


myconnection');

var bodyParser=require('body-parser');
node_crud_mysql_ejs
var flash=require('express-flash');

var cookieParser=require('cookie-parser');

var session=require('express-session');

var methodOverride=require('method-override');

var expressValidator=require('express-validator');

var config=require('./config');

var students=require('./controllers/student');

app.use(bodyParser.urlencoded({extended:true}));

app.use(bodyParser.json());
ENI RV NodeJS et ExpressJS p.64

________________________________________________________________________________________________
app.use(cookieParser('keyboard cat')); return method;

app.use(session({ }

secret:'venot123', }));

resave:false, app.use('/',students);

saveUninitialized:true, app.listen(3000,function(){

cookie:{maxAge:60000} console.log('Server running at port 3000:


http://localhost:3000');
}));
});
app.use(flash());

Controllers
var dbOptions={
Student.js
host: config.database.host,
var express=require('express');
user: config.database.user,
var router =express();
password:config.database.password,
var dateTime=require('node-datetime');
port: config.database.port,
var dt=dateTime.create();
database:config.database.db
var curdate=dt.format('Y-m-d H:M:S');
app.use(myConnection(mysql,dbOptions,'pool'));
const{check,validationResult}=require('express-
app.set('view engine','ejs'); validator');

app.set("views", "./views"); //following route to the get of student list

//app.set('views', path.join(__dirname, 'views')); router.get('/',function(req,res,next){

app.use(express.static("public")); req.getConnection(function(error,conn){

//app.use('/assets',express.static(__dirname + conn.query('SELECT * FROM students


'/public')); ORDER BY id DESC',function(err,rows,fields){

if(err){

app.use(methodOverride(function(req,res){ res.render('index',{

if(req.body && typeof req.body =='object' && title:'Student List',


'_method'in req.body){
})
// look in urlencoded POST bodies and delete it
}else{
var method=req.body._method;
res.render('index',{
delete req.body._method;
ENI RV NodeJS et ExpressJS p.65

________________________________________________________________________________________________
title:' DEMO CRUD ETUDIANTS check('txtMobile').not().isEmpty().withMessage('
AVEC EXPRESSJS', Mobile is Required Field')

data:rows, ],

errors:'' function(req,res){

}); const errors=validationResult(req);

} if(!errors.isEmpty()){

}); res.render('add',{

}); errors:errors.array(),

}); title:'Add New User',

//following route to the show add student form errors:'',

router.get('/add',function(req,res,next){ txtFname:req.body.txtFname,

res.render('add',{ txtLname:req.body.txtLname,

title:'Add New Student', txtEmail:req.body.txtEmail,

errors:'', txtMobile:req.body.txtMobile

txtFname:'', });

txtLname:'', }else{

txtEmail:'',

txtMobile:'' var student={

}) first_name:req.body.txtFname.trim(),

}); last_name:req.body.txtLname.trim(),

email:req.body.txtEmail.trim(),

//following route to the add student data mobile:req.body.txtMobile.trim(),

router.post('/add',[ created_at:curdate

check('txtFname').not().isEmpty().withMessage( }
'First Name is Required Field'),

check('txtLname').not().isEmpty().withMessage(
'Last Name is Required Field'), req.getConnection(function(error,conn){

check('txtEmail').isEmail().normalizeEmail().with conn.query('INSERT INTO students


Message('Email is Not Valid'), SET ?',student,function(err,result){
ENI RV NodeJS et ExpressJS p.66

________________________________________________________________________________________________
req.flash('success','Data added errors:'',
successfully!')
id:rows[0].id,
res.render('add',{
txtFname:rows[0].first_name,
title:'Add New Student',
txtLname:rows[0].last_name,
errors:'',
txtEmail:rows[0].email,
txtFname:'',
txtMobile:rows[0].mobile,
txtLname:'',
created_at:curdate
txtEmail:'',
});
txtMobile:''
}
});
});

});
});
});
});

}
//following route to the edit student data
});
router.put('/edit/(:id)',[

check('txtFname').not().isEmpty().withMessage(
//following route to the show edit form student data 'First Name is Required Field'),
check('txtLname').not().isEmpty().withMessage('L
router.get('/edit/(:id)',function(req,res,next){ ast Name is Required Field'),
check('txtEmail').isEmail().normalizeEmail().withM
req.getConnection(function(error,conn){ essage('Email is Not Valid'),
check('txtMobile').not().isEmpty().withMessage('M
conn.query('SELECT * FROM students WHERE obile is Required Field')
id = '+req.params.id,function(err,rows,fields){
],
if(rows.length<=0){
function(req,res){
req.flash('error','Student not found with
id = '+req.params.id); const errors=validationResult(req);

res.redirect('/');

} if(!errors.isEmpty()){

else{ res.render('edit',{

res.render('edit',{ errors:errors.array(),

title:'Edit Student', title:'Edit User',


ENI RV NodeJS et ExpressJS p.67

________________________________________________________________________________________________
id:req.params.id, });

txtFname:req.body.txtFname, });

txtLname:req.body.txtLname, }

txtEmail:req.body.txtEmail, });

txtMobile:req.body.txtMobile

}); //Below following route to the delete student data

}else{ router.delete('/delete/(:id)',function(req,res,next){

var student={ var student={id:req.params.id};

first_name:req.body.txtFname.trim(),

last_name:req.body.txtLname.trim(), req.getConnection(function(error,conn){

email:req.body.txtEmail.trim(), conn.query('DELETE FROM students


WHERE id =
mobile:req.body.txtMobile.trim() '+req.params.id,student,function(err,result){

} if(err){

req.getConnection(function(error,conn){ res.redirect('/');

conn.query('UPDATE students SET ? }else{


WHERE id =
'+req.params.id,student,function(err,result){ req.flash('success','Student deleted
successfully! id = '+req.params.id);
req.flash('success','Data updated
successfully!') res.redirect('/');

res.render('edit',{ }

title:'Edit Student', });

errors:'', });

id:req.params.id, });

txtFname:req.body.txtFname, module.exports=router;

txtLname:req.body.txtLname,

txtEmail:req.body.txtEmail, views

txtMobile:req.body.txtMobile index.ejs

}); <!DOCTYPE html>

<html lang="en">
ENI RV NodeJS et ExpressJS p.68

________________________________________________________________________________________________
<head> <div class="row">

<title>Bootstrap Example</title> <div class="col-lg-10 text-center"><h2><%=title


%></h2></div>
<meta charset="utf-8">
<div class="col-lg-2"><a href="/add" class="btn
<meta name="viewport" content="width=device- btn-primary">Add NewStudent</a></div>
width, initial-scale=1">
</div>
<link href="/assets/css/bootstrap.css"
rel="stylesheet"type="text/css"/> <table class="table table-bordered">

<script <thead>
src="/assets/js/jquery.min.js"></script>
<tr>
<script src="/assets/js/bootstrap.min.js"></script>
<th>FirstName</th>

<th>LastName</th>
</head>
<th>Email</th>
<body>
<th>Mobile</th>

<th>Action</th>
<!-- <h1><%=title%></h1> -->
</tr>
<div class="container"style="margin-top: 50px;">
</thead>
<% if(errors){%>
<tbody>
<ul class="alert alert-danger">
<% if(data){%>
<% for(var i=0;i<errors.length;i++){%>
<% data.forEach(function(student){%>
<li><%=errors[i].msg%></li>
<tr>
<%}%>
<td><%=student.first_name%></td>
</ul>
<td><%=student.last_name%></td>
<%}%>
<td><%=student.email%></td>
<% if(messages.success){%>
<td><%=student.mobile%></td>
<div class="alert alert-success">
<td>
<strong>Success!</strong><%-
messages.success%> <div style="float:left">

</div> <a href='/edit/<%=student.id%>'class="btn btn-


info">Edit</a>
<%}%>
<form method="post" action="/delete/<
%=student.id%>" style="float:right">
ENI RV NodeJS et ExpressJS p.69

________________________________________________________________________________________________
<input type="submit" name="delete" </head>
value='Delete' class="btn btn-danger"
onClick="return confirm('Are you sure you want to <body>
delete?')"/>
<div class="container"style="margin-top: 50px;">
<input type="hidden" name="_method"
value="DELETE"/> <%if(errors){%>

</form> <ul class="alert alert-danger">

</div> <%for(vari=0;i<errors.length;i++){%>

</td> <li><%=errors[i].msg%></li>

</tr> <%}%>

<%})%> </ul>

<%}%> <%}%>

</tbody> <%if(messages.success){%>

</table> <div class="alert alert-success">

</div> <strong>Success!</strong><%-
messages.success%>
</body>
</div>
</html>
<%}%>

Add.ejs
<div class="row">
<!DOCTYPE html>
<div class="col-lg-10 text-center"><h3><%=title
<html lang="en"> %></h3></div>

<head> <div class="col-lg-2"><a href="/"class="btn btn-


primary">ListStudent</a></div>
<title>Bootstrap Example</title>
</div>
<meta charset="utf-8">
<form class="form-horizontal" action="/add"
<meta name="viewport" content="width=device- method="POST">
width, initial-scale=1">
<div class="form-group">
<link href="/css/bootstrap.css"
rel="stylesheet"type="text/css"/> <label class="control-label col-sm-2"
for="txtFname">First Name:</label>
<script src="/js/jquery.min.js"></script>
<div class="col-sm-10">
<script src="/js/bootstrap.min.js"></script>
ENI RV NodeJS et ExpressJS p.70

________________________________________________________________________________________________
<input type="text" name="txtFname" <div class="col-sm-offset-2 col-sm-10">
class="form-control" id="txtFname" value="<
%=txtFname%>"/></td> <button type="submit" class="btn btn-
primary">Add</button>
</div>
</div>
</div>
</div>
<div class="form-group">
</form>
<label class="control-label col-sm-2"
for="txtLname">First Name:</label>

<div class="col-sm-10"> </div>

<input type="text" name="txtLname" </body>


class="form-control" id="txtLname" value="<
%=txtLname%>"/></td> </html>

</div>

</div> Edit.ejs

<div class="form-group"> <!DOCTYPE html>

<label class="control-label col-sm-2" <html lang="en">


for="txtEmail">Email:</label>
<head>
<div class="col-sm-10">
<title>Bootstrap Example</title>
<input type="email" name="txtEmail"
class="form-control" id="txtEmail" value="< <meta charset="utf-8">
%=txtEmail%>"/></td>
<meta name="viewport" content="width=device-
</div> width, initial-scale=1">

</div> <link href="/assets/css/bootstrap.css"


rel="stylesheet"type="text/css"/>
<div class="form-group">
<script
<label class="control-label col-sm-2" src="/assets/js/jquery.min.js"></script>
for="txtMobile">Mobile:</label>
<script src="/assets/js/bootstrap.min.js"></script>
<div class="col-sm-10">
</head>
<input type="text" name="txtMobile"
class="form-control" id="txtMobile" value="< <body>
%=txtMobile%>"/></td>
<div class="container" style="margin-top: 50px;">
</div>
<% if(errors){%>
</div>
<ul class="alert alert-danger">
<div class="form-group">
<%for(var i=0;i<errors.length;i++){%>
ENI RV NodeJS et ExpressJS p.71

________________________________________________________________________________________________
<li><%=errors[i].msg%></li> <label class="control-label col-sm-2"
for="txtLname">First Name:</label>
<%}%>
<div class="col-sm-10">
</ul>
<input type="text" name="txtLname"
<%}%> class="form-control" id="txtLname" value="<
%=txtLname%>"/></td>

</div>
<%if(messages.success){%>
</div>
<div class="alert alert-success">
<div class="form-group">
<strong>Success!</strong><%-
messages.success%> <label class="control-label col-sm-2"
for="txtEmail">Email:</label>
</div>
<div class="col-sm-10">
<%}%>
<input type="email" name="txtEmail"
<div class="row"> class="form-control" id="txtEmail" value="<
%=txtEmail%>"/></td>
<div class="col-lg-10 text-center"><h3><%=title
%></h3></div> </div>

<div class="col-lg-2"><a href="/"class="btn btn- </div>


primary">ListStudent</a></div>
<div class="form-group">
</div>
<label class="control-label col-sm-2"
for="txtMobile">Mobile:</label>

<form class="form-horizontal" action="/edit/<%=id <div class="col-sm-10">


%>" method="POST">
<input type="text" name="txtMobile"
<input type="hidden" name="_method" class="form-control" id="txtMobile" value="<
value="PUT"/> %=txtMobile%>"/></td>

<div class="form-group"> </div>

<label class="control-label col-sm-2" </div>


for="txtFname">First Name:</label>
<div class="form-group">
<div class="col-sm-10">
<div class="col-sm-offset-2 col-sm-10">
<input type="text" name="txtFname"
class="form-control" id="txtFname" value="< <button type="submit" class="btn btn-
%=txtFname%>"/></td> primary">Update</button>

</div> </div>

</div> </div>

<div class="form-group"> </form>


ENI RV NodeJS et ExpressJS p.72

________________________________________________________________________________________________

</div>

</body>

</html>

Le client envoie une requête au serveur via une


Demarrer le serveur : node app.js requête HTTP et le serveur fournit une réponse
via une réponse HTTP.
console.log('Server running at port 3000: La réponse a été donnée par le serveur,
http://localhost:3000'); généralement au format HTML.

On sait que les applications Android et iOS n'ont


pas besoin de HTML comme réponse du serveur.
Parce qu'Android et iOS utilisent des langages de
programmation différents et ne reconnaissent pas
le HTML.
C'est pourquoi on doit créer une API RESTful.

L'API RESTful renvoie uniquement des données


en réponse de tout format JSON ou XML. Et cela
peut économiser la bande passante du serveur.
Cette réponse de données peut être utilisée pour
plusieurs plates-formes à partir de différents
langages de programmation d'application.
Cette réponse de données, est généralement au
format JSON ou XML, TEXT/HTML .

Mais le plus couramment utilisé est JSON.

Dans ce tutoriel, nous allons créer une API


RESTful avec la réponse des données au format
JSON.

Voici l'architecture de l'API RESTful:

Création des API RESTful à l'aide de Node.js et


MySQL

Qu'est-ce que l'API RESTful?

REST (REpresentational State Transfer) est une


architecture de méthode de communication qui
utilise le protocole HTTP pour échanger des
données entre le client et le serveur.

Pourquoi avons-nous besoin de créer une API


RESTful?

L'architecture traditionnelle de la communication


de données entre le client et le serveur :
ENI RV NodeJS et ExpressJS p.73

________________________________________________________________________________________________
CREATETABLE product(
product_id INT(11)
PRIMARYKEYAUTO_INCREMENT,
product_name VARCHAR(200),
product_price INT(11)
)ENGINE=INNODB;

Insertion de quelques données

INSERT INTO
product(product_name,product_price) VALUES
('Product 1','2000'),
('Product 2','5000'),
('Product 3','4000'),
('Product 4','6000'),
('Product 5','7000');

Le client peut provenir de diverses plates-formes,


Étape 3. Installer les dépendances
telles que l'application Web, de bureau ou mobile.
Avant d'installer les dépendances sur node.js,
Etape #1. Definir l’API RESTful API
 créer un nouveau dossier nommé restful-
api
RESTful API utilise des verbes HTTP verbs :
$ cd restful-api
GET, POST, PUT, and DELETE. comme CRUD
Pour créer package.json, vous pouvez
(Create-Read-Update-Delete).
exécuter la commande suivante
Dans cet exemple , on va montrer comment créer
$ npm init -yes
une simple RESTful API pour récuperer des
 installer 3 dépendances suivantes en
données du serveur (GET), envoyer une
utilisant NPM (Node Package Manager):
nouvelle donnée au serveur (POST), modifier des
1. Express (cadre node.js)
données du serveur (PUT), et supprimer des
2. MySQL (pilote MySQL pour node.js)
données du serveur (DELETE) issuses d’une
3. Body-parser (middleware pour gérer la
table d’une base de données « product. »
demande de post-body)
Voici la designation des API RESTful à creer:
$ npm install --save express mysql body-
parser

fichier package.json
{
"name": "restful-api",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo "Error: no test specified" && exit 1"
},
"author": "M Fikri",
"license": "ISC",
"dependencies": {
Etape #2. Creer une base de données MYsql "body-parser": "^1.18.3",
restful_db et une table product "express": "^4.16.4",
"mysql": "^2.16.0"
CREATEDATABASE restful_db;
ENI RV NodeJS et ExpressJS p.74

________________________________________________________________________________________________
} CORS (le caractère générique * permet
} l'accès depuis n'importe quelle origine

Inclusion du module CORS (Cross Origin


Resource Sharing) dans une app web NodeJS
Étape 4. Créer un fichier Index.js
Vous pouvez inclure la fonctionnalité CORS
pour gérer les demandes interdomaines de 2
manières :

1. Installer le module # npm install --save


cors

Pour utiliser CORS dans l’application ExpressJs

# app.js
index.js

const express = require('express');


var express = require('express');
const bodyParser = require('body-parser');
var cors = require('cors');
const app = express();
var app = express();
const mysql = require('mysql');
app.use(cors());
// pour accepter toutes les requites clientes
// var cors = require('cors');
- On peut l’activer et CORS sur une seule // app.use(cors());
requete comme suit :: app.use(function(req, res, next) {
## app.js res.header("Access-Control-Allow-Origin", "*");
var express = require('express'); res.header("Access-Control-Allow-Headers",
var cors = require('cors'); "Origin, X-Requested-With, Content-Type,
var app = express(); Accept");
next();
app.get('/products/:id', cors(), function (req, });
res, next) {
res.json({msg: 'This is CORS-enabled for // parse application/json
a Single Route'}); app.use(bodyParser.json());
});
//create database connection
2. On peut aussi activer le module CORS const conn = mysql.createConnection({
sans besoin de module externe comme host: 'localhost',
suit user: 'root',
password: '',
## app.js database: 'restful_db'
app.use(function(req, res, next) { });
res.header("Access-Control-Allow-
Origin", "*"); //connect to database
res.header("Access-Control-Allow- conn.connect((err) =>{
Headers", "Origin, X-Requested-With, if(err) throwerr;
Content-Type, Accept"); console.log('Mysql Connected...');
next(); });
});
//show all products
L'en-tête Access-Control-Allow-Origin app.get('/api/products',(req, res) => {
détermine quelles origines sont autorisées let sql = "SELECT * FROM product";
à accéder aux ressources du serveur via let query = conn.query(sql, (err, results) => {
if(err) throwerr;
ENI RV NodeJS et ExpressJS p.75

________________________________________________________________________________________________
// res.send(JSON.stringify({"status": 200, "error": });
null, "resultat": results}));
return res.send(JSON.stringify({"status": 200, //Server listening
"error": null, "resultat": results})); app.listen(3000,() =>{
// return res.send({"status": 200, "error": null, console.log('Server started on port 3000...');
"resultat": results});
// return res.send(results); });

}); Étape n ° 5. Essai


});
Pour tester l'API, il existe de nombreux outils que
//show single product vous pouvez utiliser mais le plus connu est
app.get('/api/products/:id',(req, res) => { POSTMAN
let sql = "SELECT * FROM product WHERE
product_id="+req.params.id; Demarrer le projet :
let query = conn.query(sql, (err, results) => {
if(err) throwerr;  node index
res.send(JSON.stringify({"status": 200, "error":
null, "resultat": results}));
});
});

//add new product


app.post('/api/products',(req, res) => {
let data = {product_name:
req.body.product_name, product_price:
req.body.product_price};
let sql = "INSERT INTO product SET ?";
let query = conn.query(sql, data,(err, results) => {
if(err) throwerr;
res.send(JSON.stringify({"status": 200, "error":
null, "resultat": results}));
});
});

//update product
app.put('/api/products/:id',(req, res) => {
let sql = "UPDATE product SET
product_name='"+req.body.product_name+"',
#1. Obtenir tous les produits Get All Products
product_price='"+req.body.product_price+"'
(GET)
WHERE product_id="+req.params.id;
let query = conn.query(sql, (err, results) => {
Ouvrir POSTMAN, et taper l’URL suivant dans
if(err) throwerr;
Postman URL
res.send(JSON.stringify({"status": 200, "error":
:
null, " resultat ": results}));
http://localhost:3000/api/products
});
});
Selectionner la methode "GET", et cliquer sur le
bouton Send , et les resultats
//Delete product
app.delete('/api/products/:id',(req, res) => {
let sql = "DELETE FROM product WHERE
product_id="+req.params.id+"";
let query = conn.query(sql, (err, results) => {
if(err) throwerr;
res.send(JSON.stringify({"status": 200, "error":
null, " resultat ": results}));
});
ENI RV NodeJS et ExpressJS p.76

________________________________________________________________________________________________

#3. Creer un nouveau poduit (POST)

taper l’URL suivant :


http://localhost:3000/api/products
Selectionner la methode “POST", ensuite entrer
les données suivantes dans la colonne JSON
(application / json) ou Body/raw
{
“title": "Product xx,
“description": "Product xx,
"product_code: “codexx",
}
cliquer sur le bouton et les resultats apparaissent
en bas comme suit

#2. Récupérer un seul produit Get Single


Product (GET)

taper l’URL suivant :


http://localhost:3000/api/products/2
Selectionner la methode "GET", et cliquer sur le
bouton Send , et les resultats apparaissent en
bas comme suit
ENI RV NodeJS et ExpressJS p.77

________________________________________________________________________________________________

#5 Supprimer un produit (DELETE)

Après insertion/modification/suppression , on peut


verifier avec la commande:
taper l’URL
mysql> SELECT * FROM products;
suivant : :http://localhost:3000/api/products/6
Selectionner la methode “DELETE", et cliquer
sur le bouton Send , et les resultats apparaissent
en bas comme suit
#4. Modifier un produit Update Product (PUT)

taper l’URL suivant :


http://localhost:3000/api/products/2
Selectionner la methode “PUT", ensuite entrer
les données suivantes dans la colonne JSON
(application / json) ou Body/raw
{
“title": "Product zz,
“description": "Product zz,
"product_code: “codezz",
}
cliquer sur le bouton et les resultats apparaissent
en bas comme suit
ENI RV NodeJS et ExpressJS p.78

________________________________________________________________________________________________
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;

public class HttpURLConnectionExample {

public static void main(String[] args)


throws Exception {

HttpURLConnectionExample http =
new HttpURLConnectionExample();

System.out.println("GET Request
Using HttpURLConnection");
http.sendGet();
}

// HTTP GET request


private void sendGet() throws Exception
{

Consommation de l’API RESTFULL Express- String url =


NodeJs "http://localhost:3000/api/products'";

CLIENT PHP URL obj = new URL(url);

HttpURLConnection con =
<?php (HttpURLConnection) obj.openConnection();
$url ="http://localhost:3000/api/products'"; con.setRequestMethod("GET");
con.setRequestProperty("Accept-
// pass the java restful URL Charset", "UTF-8");
$client = curl_init($url); System.out.println("Response Code
curl_setopt($client,CURLOPT_RETURNTRANSF : " + con.getResponseCode());//200
ER,1); System.out.println("Response
$response = curl_exec($client); Message : " + con.getResponseMessage());// OK
//$result = json_decode($response);
if(!empty($response)) BufferedReader in = new
{ BufferedReader(
echo $response; new
} InputStreamReader(con.getInputStream()));
else String line;
{ StringBuffer response = new
echo "No data found"; StringBuffer();
}
?> while ((line = in.readLine()) != null)
{
response.append(line);
CLIENT JAVA }
in.close();
import java.io.BufferedReader;
import java.io.DataOutputStream;
ENI RV NodeJS et ExpressJS p.79

________________________________________________________________________________________________
<td><button type="button" name="edit"
System.out.println(response.toString()); class="btn btn-primary btn-xs edit"
@click="fetchData(contact.id)">Edit</button></td>
} <td><button type="button" name="delete"
class="btn btn-danger btn-xs delete"
} @click="deleteData(contact.id)">Delete</button><
/td>
CLIENT VUEJS
</tr>
</table>
<!DOCTYPE html>
<html lang="en"> </div>
<head> </div>
<meta charset="UTF-8"> </div>
<link rel="stylesheet" type="text/css"
href="css/bootstrap.min.css"/> <script>
<script src="js/vue.min.js"></script> var app = new Vue({
<script src="js/axios.min.js"></script> el: '#vueapp',
<script type="text/javascript" data: {
src="js/bootstrap.min.js"></script> name: '',
</head> email: '',
<body> country: '',
city: '',
<!-- Content Section -->> job: '',
<div class="row"> contacts: []
<div class="col-md-12"> },
<h1>Demo: VueJS and MySQL CRUD mounted: function () {
Operations using ExpressJs</h1> console.log('Hello from Vue!');
</div> this.getContacts();
</div> },
<div class="row" > methods: {
<div class="col-md-12"> getContacts: function(){
<div class="pull-right">
<button class="btn btn-success" data- axios.get('http://localhost:3000/api/products'')
toggle="modal" data- .then(function (response) {
target="#add_new_record_modal">Add New // console.log(response.data);
Record</button> // alert(" Message:
</div> "+response.data.status);
</div> app.contacts = response.data.resultat;
</div>
<div class="row" id='vueapp'> })
<div class="col-md-12"> .catch(function (error) {
<h3>Records:</h3> console.log(error);
<table class="table table-bordered table- });
striped"> }
<tr>
<th>Name</th> }
<th>Email</th> })
</script>
</tr> </body>
</html>
<tr v-for='contact in contacts'>
<td>{{ contact.name }}</td>
<td>{{ contact.email }}</td>
ENI RV NodeJS et ExpressJS p.80

________________________________________________________________________________________________

Dans le champ find de la fenêtre modale « Eclipse


market », on entrera « enide » et on lancera la
D’autres frameworks de NodeJs : sails.js recherche en appuyant sur Go :
MVC et Sequelize

Utilisation du plugin Enide pour développer


des applications Node.js avec Eclipse

Le plugin Enide 2015

Enide signifie Eclipse Node IDE. Ce plugin est


développé et soutenu par l'équipe « nodeclipse »
qui héberge son projet sur GitHub, visible ICI.

III. Installation de l'environnement de


développement

III-A. Prérequis

Il faut en premier lieu disposer au minimum du


JDK 7 ou 8,

III-B. Installation du plugin ENIDE


Une fois la recherche dans l'entrepôt terminée, on
choisira « Enide (Studio) 2015 » :
Toutes les opérations d'installation se feront
directement depuis Eclipse.

Dans un premier temps, on fera appel à l'entrepôt


« Eclipse Marketplace » pour importer le plugin :
ENI RV NodeJS et ExpressJS p.81

________________________________________________________________________________________________

On acceptera toutes les caractéristiques On acceptera également le code non signé :


proposées par défaut :

Puis on redémarrera Eclipse pour terminer


l'installation.

Au redémarrage d'Eclipse on remarquera que la


barre des outils s'est enrichie de quelques icônes,
propres au nouveau plugin. C'est la preuve que
On acceptera également les termes de la licence : l'installation s'est correctement déroulée.

IV. Créer un projet node.js▲

Nous créerons un nouveau projet à l'aide de la


commande fichier → new → other :
ENI RV NodeJS et ExpressJS p.82

________________________________________________________________________________________________

On choisira alors dans l'assistant « Node.js Notre projet est alors créé. Nous pouvons
Project » : d'ailleurs le constater dans l'explorateur de projet :

Eclipse a importé les bibliothèques nécessaires et


a créé un fichier hello-world-server.js.

Ce fichier hello-world-server.js contient déjà le


code minimaliste pour créer un serveur HTTP qui
écoute sur le port 1337 et renvoie Hello World :

Nous appellerons notre projet « sampleNode » et


nous choisirons d'utiliser le modèle « Hello
World » :

V. Tester une application Node.js▲


ENI RV NodeJS et ExpressJS p.83

________________________________________________________________________________________________
Une application node.js est testable directement • https://github.com/expressjs/body-parser
dans Eclipse. Pour le montrer, nous allons tester • https://github.com/expressjs/multer/
notre projet sampleNode. • http://naltatis.github.io/jade-syntax-
docs/#basics
Pour ce faire, il suffit de faire un clic droit sur le • https://developer.mozilla.org/en-
fichier hello-world-server.js dans l'explorateur de US/docs/Learn/Server-
projet et de choisir de l'exécuter comme node side/Express_Nodejs/Introduction
application : Express/Node introduction
• https://nodejs.org/en/docs/ About
documentation
• https://developer.ibm.com/languages/node
-js/tutorials/learn-nodejs-expressjs/
Using Express.js for Node applications

L'exécution est visible dans la console Eclipse :

Et si nous testons cette URL :


http://127.0.0.1:1337/, nous pouvons vérifier
qu'elle retourne dans le navigateur « Hello
World ».

NB : pour ajouter d’autres modules dans le projet


eclipse, il faut aller d’abord dans le projet et lancer
la commande npm install nom_module

Liens

• http://en.wikipedia.org/wiki/Node.js
• http://openclassrooms.com/courses/des-
applications-ultra- rapides-avec-node-js
• http://expressjs.com/4x/api.html

Vous aimerez peut-être aussi