Un framework d'application Web Node.JS est puissant et permet de mettre en place facilement un serveur HTTP grâce au module éponyme. Néanmoins, il est souvent plus simple de passer par un framework d'application Web comme Express Express facilite: Le routage des requêtes L'analyse du corps et des en-têtes des requêtes La gestion des Session et Cookies L'usage de templates La gestion de fichiers Statiques La gestion des logs,... Un framework d'application Web Une application Express.js est en général composée des sections suivantes: 1. Les dépendances: un ensemble d'instructions de type require() pour gérer les dépendances. 2. Les instanciations: un ensemble d'instructions pour créer des objets: le serveur, le logger,... 3. Les configurations: un ensemble d'instructions pour configurer l'application. 4. Les middleware: un ensemble d'instructions de type use() pour activer les middlewares. 5. Les routes: un ensemble d'instructions de type use() pour définir les routes et pages. 6. Le lancement: un ensemble d'instructions pour démarrer le serveur sur un port réseau donné. 1
Un exemple: très simple var app = require('express')(); app.get('/', function(req, res) { res.send('hello World!'); app.get('/help', function(req, res) { res.send( Pas d aide pour le moment'); app.listen(8080); Les middleware Dans express, un middleware est un processus qui va se placer entre la requête et l envoi de la réponse (un peu comme un filtre pour les Servlet Java). Tous les traitements qui consistent à récupérer la requête, la manipuler, et renvoyer une réponse, sont des middlewares. Le routage, par exemple n est qu un middleware parmi d autres. On peut facilement créer son propre middleware, ou utiliser un middleware prédéfini. Dans Express 3 (basé sur le framework Connect) un certain nombre de middlewares sont inclus (comme dans Connect). 2
Les middleware Express 4 (version courante en 2015) n'est plus basé sur Connect. Conséquences: certains middleware changent de noms, d'autres disparaissent, enfin il faut maintenant installer 1 par 1 les middleware avec npm: { // Exemple de fichier package.json pour Express 4.0 } "name": "exemple", "main": "server.js", "dependencies": { } "express": "~4.0.0", "morgan": "~1.0.0", "body-parser": "~1.0.0", // Module node // Middleware // Middleware "method-override": "~1.0.0" // Middleware Un exemple: log des requêtes Exemple de log des requêtes avec notre propre middleware: var app = require('express')(); app.use(function(req, res, next) { console.log('%s %s', req.method, req.url); next(); app.get('/', function(req, res) { res.send('hello World!'); app.get('/help', function(req, res) { res.send( Pas d aide pour le moment'); app.listen(8080); 3
Exemple amélioré Plus simplement, on aurait pu utiliser le middleware prédéfini "morgan" (à condition de l'avoir installé au préalable): var app = require('express')(); var morgan=require('morgan'); app.use(morgan('tiny')); app.get('/', function(req, res) { res.send('hello World!'); app.get('/help', function(req, res) { res.send('pas d aide pour le moment'); app.listen(8080); Les middleware Le middleware est, dans l'exemple qui précède, simplement une fonction. Attention! : l'ordre d'apparition des middleware est important, il conditionne l'ordre dans lequel ils sont exécutés. L'appel à next() indique que l'on souhaite continuer la chaîne des middlewares. Si on interrompt ici cette chaîne, le middleware devra se charger de répondre lui-même au client. 4
Un exemple: comptage des hits var express = require('express'); var Session = require('cookie-session'); var app = express(); app.use(session({secret: "dg9wc2vjcmv0"})); app.use(function(req, res) { var sess = req.session; sess.hits = sess.hits 0; sess.hits++; res.send("visits:"+ sess.hits ); app.listen(8080); console.log('express started on port 8080'); Les middleware Un middleware peut être limité à un préfixe d URL ou à une route particulière: app.use('/commande', function(req, res, next) { // Filtre exécuté pour toutes les URLs // commençant par "/commande " next(); Attention, les paramètres req et res sont les mêmes pour tout le monde; si un middleware modifie, par exemple, l objet req, cette modification concerne les middleware suivants. 5
Middleware prédéfinis Voici quelques exemples de middleware prédéfinis: body-parser: analyse les entrées d'un formulaire HTML issu d une requête et les stocke dans un objet JavaScript: req.body compression: compresse/décompresse requête et réponse connect-timeout: permet d'associer un timeout au traitement de la requête cookie-parser: analyse l'en-tête HTTP pour en extraire les cookies et les stocker dans req.cookies. cookie-session: associe une session à chaque visiteur (authentifié ou non) Middleware prédéfinis csurf: pour se protéger des attaques de type CSRF (Crosssite request forgery) errorhandler: permet, en phase de dev., de voir une trace complète des erreurs dans le browser express-session: gestion souple des sessions method-override: permet d'utiliser les différents verbes HTTP (PUT,DELETE,...) même si le client ne les connaît pas. Souvent utilisé pour mettre en place un service REST morgan: gestion des logs des requêtes 6
Middleware prédéfinis response-time: calcule le temps de réponse des requêtes et l'enregistre dans l'en-tête de la réponse faite au client. serve-favicon: répond (efficacement) aux requêtes clientes (souvent intempestives) de favicon (utilise un cache) serve-index: permet de retourner le contenu listé d'un répertoire serve-static: pour servir efficacement les fichiers statiques (seul module intégré dans Express 4) vhost: gestion du "virtual hosting" Le routage Express propose la méthode route() pour créer une "Route". On peut ensuite utiliser les verbes HTTP sur cette route ou lui ajouter des middleware. app.route('/commandes').get(function(req, res, next) { }) // Actions à faire lors de l utilisation de la méthode get.post(function(req, res, next) { // Actions à faire lors de l utilisation de la méthode post 7
Le routage On peut obtenir le même résultat avec l API Router: var cmd= express.router(); cmd.get(('/', function(req, res, next) { // Actions à faire lors de l utilisation de la méthode get }) cmd.post('/', function(req, res, next) { // Actions à faire lors de l utilisation de la méthode post app.use('/commande', cmd); Le routage Express vous permet de gérer des routes dynamiques: dont certaines portions peuvent varier. La syntaxe :nomvariable dans l'url de la route a pour effet de créer un paramètre accessible depuis req.params.nomvariable. app.get('/etage/:num/chambre', function(req, res) { res.setheader('content-type', 'text/plain'); res.end('vous êtes à la chambre de l\'étage n ' + req.params.num); 8
Le routage Cela vous permet de créer de "belles" URLs et vous évite d'avoir à passer par le suffixe ("?num=2") pour gérer des variables. C'est à la fonction de callback de vérifier que le paramètre est bien un nombre et de renvoyer une erreur si ce n'est pas le cas. Les templates Express permet d'utiliser des templates pour aider à la production de la page HTML. Un moteur de template propose un langage (normalement simple à utiliser) pour permettre de produire du HTML et d'insérer dans celui-ci un contenu variable. Il existe de nombreux moteurs de templates (Twig, Smarty, Haml, JSP, Jade, EJS...) et Express permet d'utiliser la plupart d'entre eux. 9
Les templates Le principe général d'utilisation est le suivant: depuis le fichier JavaScript, on référence le template de son choix en lui transmettant les variables dont il a besoin pour construire la page. Par exemple avec EJS (Embedded JavaScript): app.get('/etage/:num/chambre', function(req, res) { res.render('chambre.ejs', {etage: req.params.num chambre.ejs (sous-dossier "views"): <h1>vous êtes dans la chambre</h1> <p>vous êtes à l'étage n <%= etage %></p> Les concurrents? Express.js est aujourd'hui, et d'assez loin, le frameworkweb pour Node.js le plus populaire. Toutefois, il existe des alternatives comme: Koa: du même auteur qu' Express, il a une empreinte mémoire très faible et est compatible avec EcmaScript 6. Hapi: plus de configuration, moins de code à écrire. Sails.js: plus complet (mais aussi plus lourd) qu'express.js 10