I. HTTP Web Servers▲
Le module HTTP de la bibliothèque Node est polyvalent. Vous pouvez l'utiliser en tant que client pour parcourir des sites Web, mais également en tant que serveur. Ici, nous allons l'utiliser en tant que serveur de fichiers issus de notre système de fichiers local.
Si Python, Ruby ou http-server vous sont familiers, c'est alors équivalent à cela
Implémentations des serveurs http existant
# version avec python
python -m SimpleHTTPServer 9000
# version avec ruby
ruby -run -e httpd . -p 9000
# version avec Node (npm install http-server)
Allons-y, réalisons-le nous-même, ce n'est pas si difficile.
II. Serveur http de base▲
Un des serveurs les plus simples que vous puissiez créer avec Node ressemble à ceci :
Serveur de base server.
js
const http =
require
(
'http'
);
http.createServer
(
function (
req,
res) {
// server code
console.log
(
`
${req.method}
${req.url}
`
);
res.end
(
'hello world!'
);
}
).listen
(
9000
);
console.log
(
'Le serveur écoute le port 9000'
);
Pour le tester, sauvegardez ce code dans un fichier nommé « server.js », puis exécutez-le comme suit :
node server.js
En cliquant sur l'URL http://localhost:9000 vous devriez voir apparaître le message « hello world ! » dans votre navigateur.
Quelques explications concernant ce code s'imposent. Nous avons utilisé la fonction http.createServer avec un callback (retour). Cette fonction callback est destinée à être appelée chaque fois qu'un client se connecte au serveur. Vous remarquerez qu'il comprend deux paramètres : req, pour request (requête), et res, pour response (réponse).
La requête contient les informations du client, en l'occurrence : URL (adresse), chemin, les entêtes, les méthodes http, et d'autres choses encore.
L'objet réponse (callback) est utilisé pour répondre à la requête soumise par un client. Vous pouvez le configurer comme bon vous semble pour répondre au client et y mettre par exemple, en plus des données, des entêtes ou autre.
Enfin, la partie concernant l'écoute du serveur en attente d'une connexion. Il permet de définir le port à utiliser pour l'écoute. Dans notre cas, il s'agit du port 9000.
III. Serveur statique de fichiers Node.js avec ES6+▲
Nous allons maintenant procéder à la réalisation du serveur Web statique. Nous voulons découper l'URL fournie par le client afin d'en déduire le chemin d'accès local vers le fichier demandé. Par exemple, si la requête client est de la forme « localhost :9000/example/server.js, il nous faudra trouver un fichier local répondant au chemin relatif ./example/server.js.
Les navigateurs ne s'appuient pas directement sur les suffixes de fichiers trouvés dans les URL. Ils exploitent l'entête HTML « content-type ». Par exemple, si nous fournissons un fichier HTML en définissant un entête content-type fixé sur la valeur « text/plain », le navigateur n'interprètera pas le balisage HTML, mais l'affichera comme du texte normal, on peut aussi dire, du texte plain. Dans le cas contraire, si vous définissez un content-type fixé sur la valeur « text/html », alors votre navigateur interprètera le balisage HTML et restituera le contenu dans le respect de la mise en page définie par ce balisage. Le type de contenu (content-type) est défini par un standard que l'on appelle MIME. Il s'agit là d'un acronyme signifiant Multipurpose Internet Mail Extensions. Dans le code suivant, en ligne 15, vous pouvez voir l'ensemble des suffixes de fichiers supportés par notre serveur avec en face d'eux, le type MIME correspondant :
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
const http =
require
(
'http'
);
const url =
require
(
'url'
);
const fs =
require
(
'fs'
);
const path =
require
(
'path'
);
// vous pouvez passer le paramètre en ligne de commande. ex. node static_server.js 3000
const port =
process.
argv[
2
]
||
9000
;
http.createServer
(
function (
req,
res) {
console.log
(
`
${req.method}
${req.url}
`
);
// découpe l'URL
const parsedUrl =
url.parse
(
req.
url);
// Extrait le chemin de l'URL
let pathname =
`.
${parsedUrl.pathname}
`
;
// Associe le type MIME par rapport au suffixe du fichier demandé
const mimeType =
{
'.ico'
:
'image/x-icon'
,
'.html'
:
'text/html'
,
'.js'
:
'text/javascript'
,
'.json'
:
'application/json'
,
'.css'
:
'text/css'
,
'.png'
:
'image/png'
,
'.jpg'
:
'image/jpeg'
,
'.wav'
:
'audio/wav'
,
'.mp3'
:
'audio/mpeg'
,
'.svg'
:
'image/svg+xml'
,
'.pdf'
:
'application/pdf'
,
'.doc'
:
'application/msword'
,
'.eot'
:
'appliaction/vnd.ms-fontobject'
,
'.ttf'
:
'application/font-sfnt'
};
fs.exists
(
pathname,
function (
exist) {
if(!
exist) {
// si le fichier n'existe pas, renvoie 404
res.
statusCode =
404
;
res.end
(
`File
${pathname}
not found!`
);
return;
}
// s'il s'agit d'un répertoire, on tente d'y trouver un fichier index.html
if (
fs.statSync
(
pathname).isDirectory
(
)) {
pathname +=
'/index.html'
;
}
// lecture du fichier local
fs.readFile
(
pathname,
function(
err,
data){
if(
err){
res.
statusCode =
500
;
res.end
(
`Error getting the file:
${err}
.`
);
}
else {
// extraction du suffixe de fichier selon le chemin basé sur l'URL fournie. ex. .js, .doc, ...
const ext =
path.parse
(
pathname).
ext;
// si le fichier est trouvé, définit le content-type et envoie les données
res.setHeader
(
'Content-type'
,
mimeType[
ext]
||
'text/plain'
);
res.end
(
data);
}
}
);
}
);
}
).listen
(
parseInt
(
port));
console.log
(
`Le serveur écoute sur le port
${port}
`
);
Nous utilisons les classes utilitaires path.parse et url.parse pour décomposer l'objet request.url afin d'en extraire les informations d'adresse et de chemin afin de déduire le chemin local vers le fichier demandé. Finalement, nous utiliserons la classe utilitaire fs.readFile pour obtenir le contenu du fichier local. Si une erreur survient pendant le traitement du fichier local, une erreur 404 sera renvoyée, dans le cas contraire, c'est le contenu du fichier local qui est renvoyé.
Testons le résultat ainsi :
2.
3.
4.
5.
6.
7.
8.
9.
10.
Lignes de commande pour tester le serveur
# Démarre le serveur
node server.js
# Obtenir le fichier javascript avec
curl -i localhost:9000
/server.js
# test avec un fichier qui n'existe pas
curl -i localhost:9000
/invalid-file.doc
À l'exécution de la ligne 5, vous obtiendrez une réponse « 200 OK », alors qu'à l'exécution de la ligne 8 vous obtiendrez une erreur 404, comme nous nous y attendions.
Vous pouvez aussi télécharger le code depuis ce dépôt et l'essayer avec les fichiers suivants :
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
Tests avec différents types de fichiers
# Issu du dépôt
git clone https://github.com/amejiarosario/meanshop.git
cd meanshop
# Charge la version spécifique
git checkout static-server
# Démarre le serveur (requiert Node 4+)
npm start
# teste les URL suivantes dans votre navigateur
open http://localhost:9000
/
open http://localhost:9000
/index.html
IV. Récapitulatif▲
Dans ce tutoriel, nous avons découvert les bases du module http pour créer un serveur. Nous avons aussi parlé des types MIME et compris comment ils interagissent avec le navigateur pour restituer correctement le contenu. Finalement, nous avons utilisé toutes ces connaissances pour réaliser notre serveur statique de fichiers avec Node.js !
V. Remerciements▲
Nous remercions Adrian Meija qui nous a autorisés à publier son tutoriel Building a Node.js static file server (files over HTTP) using ES6+.
Nous tenons également à remercier Thierry Massette pour la traduction, Laethy pour la gabarisation et Claude Leloup pour la correction orthographique.