Tutoriel pour apprendre à mettre en place un serveur statique de fichiers Node.js

Servir des fichiers à travers HTTP

Adrian Meija

Traducteur

Yotta

Dans ce tutoriel, nous allons réaliser un serveur statique de fichiers à l'aide de la bibliothèque JavaScript Node.js. Ce serveur Web construira ses réponses en prélevant leur contenu dans des fichiers locaux placés dans un dossier bien précis. Tout au long de ce tutoriel, nous n'étudierons pas que le module http, d'autres modules utilitaires seront aussi abordés comme path, url et fs.

Commentez

- Titre : Tutoriel pour apprendre à mettre en place un serveur statique de fichiers Node.js

- Auteur : Adrian Meija

- Traducteur : Yotta

- Parution : 26 mai 2017

- Licence : Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright ® 2017 Adrian Meija. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- I. HTTP Web Servers

- II. Serveur http de base

- III. Serveur statique de fichiers Node.js avec ES6+

- IV. Récapitulatif

- V. Remerciements

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 :

1. const http = require('http');

2. const url = require('url');

3. const fs = require('fs');

4. const path = require('path');

5. // vous pouvez passer le paramètre en ligne de commande. ex. node static_server.js 3000

6. const port = process.argv[2] || 9000;

7. http.createServer(function (req, res) {

8. console.log(`${req.method} ${req.url}`);

9. // découpe l'URL

10. const parsedUrl = url.parse(req.url);

11. // Extrait le chemin de l'URL

12. let pathname = `.${parsedUrl.pathname}`;

13. // Associe le type MIME par rapport au suffixe du fichier demandé

14. const mimeType = {

15. '.ico': 'image/x-icon',

16. '.html': 'text/html',

17. '.js': 'text/javascript',

18. '.json': 'application/json',

19. '.css': 'text/css',

20. '.png': 'image/png',

21. '.jpg': 'image/jpeg',

22. '.wav': 'audio/wav',

23. '.mp3': 'audio/mpeg',

24. '.svg': 'image/svg+xml',

25. '.pdf': 'application/pdf',

26. '.doc': 'application/msword',

27. '.eot': 'appliaction/vnd.ms-fontobject',

28. '.ttf': 'application/font-sfnt'

29. };

30. fs.exists(pathname, function (exist) {

31. if(!exist) {

32. // si le fichier n'existe pas, renvoie 404

33. res.statusCode = 404;

34. res.end(`File ${pathname} not found!`);

35. return;

36. }

37. // s'il s'agit d'un répertoire, on tente d'y trouver un fichier index.html

38. if (fs.statSync(pathname).isDirectory()) {

39. pathname += '/index.html';

40. }

41. // lecture du fichier local

42. fs.readFile(pathname, function(err, data){

43. if(err){

44. res.statusCode = 500;

45. res.end(`Error getting the file: ${err}.`);

46. } else {

47. // extraction du suffixe de fichier selon le chemin basé sur l'URL fournie. ex. .js, .doc, ...

48. const ext = path.parse(pathname).ext;

49. // si le fichier est trouvé, définit le content-type et envoie les données

50. res.setHeader('Content-type', mimeType[ext] || 'text/plain' );

51. res.end(data);

52. }

53. });

54. });

55. }).listen(parseInt(port));

56. 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 :

1. Lignes de commande pour tester le serveur

3. # Démarre le serveur

4. node server.js

6. # Obtenir le fichier javascript avec

7. curl -i localhost:9000/server.js

9. # test avec un fichier qui n'existe pas

10. 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 :

1. Tests avec différents types de fichiers

3. # Issu du dépôt

4. git clone https://github.com/amejiarosario/meanshop.git

5. cd meanshop

6. # Charge la version spécifique

7. git checkout static-server

8. # Démarre le serveur (requiert Node 4+)

9. npm start

10. # teste les URL suivantes dans votre navigateur

11. open http://localhost:9000/

12. 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.