Introduction
Dans ce tutoriel, nous allons voir le framework Node.js, qui permet de développer rapidement un web service répondant avec des données formatées ou des pages internet.
Le modèle standard
Dans un site web traditionnel, le serveur répond aux requêtes des
clients en renvoyant le contenu d'un fichier: Si un client requiert
l'adresse http://domain.com/page.html
, typiquement le serveur du
domaine domain.com
va aller chercher le fichier page.html
, le
lire et l'envoyer sur le réseau en réponse. C'est ce que propose par
défaut les serveurs web tels que le serveur
ISS de
Microsoft, Apache, ou encore le léger
lighttpd.
Un modèle un tout petit peu plus dynamique permet à un serveur internet d'exécuter un script pour répondre à une requête, et à rediriger la sortie du script en réponse à la requête. En général, l'interface utilisée est CGI (pour Common Gateway Interface). Tous les serveurs permettent cela.
Quelques langages usuels de scripts:
- Perl (avec l'extension ".pl")
- PHP (avec l'extension ".php")
- ASP (pour Active Server Pages, essentiellement avec le serveur IIS)
- Mais aussi Python, Ruby...
Le modèle Node.js
À l'inverse de ce schéma, Node.js est un programme autonome. Il est basé sur le moteur d'exécution JavaScript V8 de Google et a été créé en 2009 par Ryan Dahl (Joyent Inc.). Écrit en C++, c'est essentiellement une plateforme d'exécution javascript avec des APIs spécialisées pour gérer le fait d'être un serveur: la gestion des connections réseaux, mais aussi le système de fichiers,... On a donc pas de "comportement par défaut", et tout doit se programmer en javascript.
Les grands principes sous-tendant Node.js sont:
- Éxécution pilotée par les événements
- Appels de fonctions asynchrones (utilisation de callback)
- Entrées/sorties non bloquantes
Les deux premiers sont "standards" dans la philosophie javascript. Le troisième principe est essentiel de la part d'un serveur: on souhaite qu'il reste réactif autant que possible.
Des exemples de l'utilisation de Node.js en production:
- Un joli site : https://tweetping.net/
- Mais aussi : Linkedin
- Et Microsoft Azure
- Et Walmart
- Et Paypal
- ...
Un serveur Web avec Node.js
Un serveur Node.js consiste au minimum en
- le programme nodejs
- un fichier javascript
Un script pour Node.js va faire les choses suivantes:
- Initialiser des objets correspondant aux librairies avec la fonction
require
- par exemple, la librairie
http
qui gère le protocole HTTP - définir un serveur
- lancer le serveur
Par exemple, voila un code minimal.
Pour l'exécuter:
- Placez ce texte dans
monserveur.js
(avecgedit
oujedit
par exemple) - Ouvrez un terminal
- Rendez-vous dans le dossier où vous avez sauvé le fichier:
- Tappez la commande
- Dans un navigateur, entrez l'adresse du serveur:
- Si le message "Hello World" s'affiche: bravo, vous avez un serveur web.
Le concept
Comme dit plus haut, le script Node.js ne fait rien tout seul: il ne
fait que réagir à des événements. Ici, on crée un objet serv
qui
contient les propriétés pour de fait être un serveur. La principale
caractéristique d'un serveur est la façon dont il réagit aux requêtes:
c'est le but de la fonction (non nommée) en argument de la méthode
createServer
. Cette fonction est appelée à chaque fois qu'un
client se connecte: elle prend en argument req
, objet qui décrit
la requête, et res
, objet que la fonction va peupler et qui décrit
la réponse HTTP (voir le cours/tuto HTTP).
- L'objet
req
est de la classehttp.IncomingMessage
- L'objet
res
est de la classehttp.ServerResponse
La deuxième chose que fait le le script est de demander au serveur de
l'objet serv
d'écouter le port 8000.
Donc le serveur ne fait rien tant qu'un client ne se connecte pas. Son
comportement est ensuite complètement décrit par la fonction
non-nommée liée par la méhode createServer
.
Voir l'échange HTTP
Avec Firefox, vous pouvez utiliser par exemple l'extension Live Http Headers.
Boucle de traitement
- Un seul programme (un seul thread) traite les événements dans l'ordre de leur occurrence
- Les traitements qui concernent les entrées/sorties sont exécutées de manière asynchrone par d'autres threads: « non blocking I/O »
Slogan:
Avec Node.js, on ne fait que spécifier des réponses à des événements
Et donc tout est virtuellement en parallèle.
Exemple: serveur plus évolué
On va utiliser la librairie "fs" qui permet d'accèder au système de fichier. Ici:
__dirname
correspond au dossier où se trouve le programme javascript (voir ce post et la doc)- La fonction
readFile()
génére un événement lorsque le fichier est ouvert (ou qu'une erreur survient), et la fonction en argument est appelée à ce moment. - Le contenu du fichier est du texte. Le serveur n'a à priori pas moyen de savoir plus. Ici, on a donné comme type de contenu
text/plain
. Vous pouvez essayertext/html
, pour voir. En général, on utilise l'extension du fichier pour lui associer un type de contenu -- mais il faut le faire faire au serveur explicitement. On peut par exemple utiliser la librairie node-mime, mais sinon plus simplement utiliser la bibliothèque express : voir plus bas.
Les bibliothèques
Node.js possède une communauté vibrante à l'origine de plus de 240000 projets, centralisée par le gestionnaire de paquets npm (Node Package Manager). Une bibliothèque Node.js s'installe avec la commande Notez que pour que cela fonctionne sur les machines du bâtiment Bréguet, il faut d'abord configurer le proxy:
En standard dans Node :
- http : pour communiquer via le protocole HTTP
- fs : pour interagir avec le système de fichiers
- timer : pour schéduler des traitements
- crypto : pour chiffrer/déchiffrer des données
Exemple de paquets accessibles le Node Package Manager (NPM) :
- jquery : pour avoir accès aux facilités de jQuery
- async : helpers pour faciliter la gestion d'appels asynchrones
- express : pour construire rapidement des applications web (plus bas dans la page)
- sqlite3 : pour connecter à une base de données SQLite (dans le tuto correspondant)
- mongoose : pour connecter à une base de données MongoDB
- ...
Applications web avec Express
La librairie express permets de développer plus simplement des applications web. En particulier, elle permet d'associer à une "route" une fonction de callback.
Dans ce schéma, une "route" est la donnée d'un mode de requête (GET ou POST) et d'un chemin depuis la racine du site.
Installation
Pour l'installer, configurer le proxy (uniquement sur les machine du bâtiment Bréguet): puis
Utilisation
On peut par exemple configurer deux routes:
Ici, à chaque "route" on associe une fonction (qui ici fait quelque chose de simple). Pour que cela fonctionne:
- Dans le répertoire du fichier javascript, placez un fichier "page.html" et un fichier "autrepage.html".
- Dans votre navigateur, essayez les addresse
et
la fonction sendfile
C'est une fonction spécifique de la librairie express, qui envoie le fichier avec le bon type mime en fonction de l'extension.
Avec des paramètres
Il est possible de récupérer les paramètres donnés dans l'url.
Essayez l'adresse http://localhost:8000/autre?donnee=hello
pour voir.
Avec express, l'attribut
query
de la
variable req
contient la liste des paires (paramètre,valeur) sous
la forme d'un objet javascript: on peut donc facilement accèder aux
paramètres d'une requête.
Note
Techniquement, le script au dessus est un service web ! Pas très intéressant, certe, mais néanmoins un service web. En utilisant les techniques du TD5, il est possible de faire une page html indépendante qui questionne ce service en ajax.