Guide du débutant pour le développement de serveurs Web avec Node.js

Pendant la majeure partie de ma carrière Web, j'ai travaillé exclusivement du côté client. Concevoir des mises en page adaptatives, créer des visualisations à partir de grandes quantités de données, créer des tableaux de bord d'application, etc. Mais je n'ai jamais eu à traiter directement le routage ou les requêtes HTTP. Jusqu'à récemment.

Ce message est une description de la façon dont j'ai appris plus sur le développement Web côté serveur à l'aide de Node.js, et une brève comparaison de l'écriture d'un simple serveur HTTP utilisant 3 environnements différents, Express, Koa.js et Hapi.js.

Remarque: si vous êtes un développeur Node.js expérimenté, vous penserez probablement que tout cela est élémentaire / simple. ¯ \ _ (ツ) _ / ¯.

Quelques bases du réseau


Lorsque j'ai commencé à travailler dans l'industrie du Web il y a quelques années, j'ai rencontré un cours sur les réseaux informatiques par le professeur David Veteral sur Coursera. Malheureusement, il n'est plus disponible, mais des conférences sont toujours disponibles sur le site Web de Pearson .

J'ai vraiment aimé ce cours car il expliquait ce qui se passait sous le capot d'une manière compréhensible, donc si vous pouvez prendre le manuel des réseaux informatiques , lisez tous les détails sur les merveilles du réseau.

image

Ici, cependant, je ne parlerai que brièvement du contexte. HTTP (Hypertext Transfer Protocol) est un protocole de communication utilisé dans les réseaux informatiques. Il en existe de nombreux sur Internet, tels que SMTP (Simple Mail Transfer Protocol) , FTP (File Transfer Protocol) , POP3 (Post Office Protocol 3) , etc.

Ces protocoles permettent aux appareils dotés d'un matériel / logiciel complètement différent de communiquer entre eux, car ils fournissent des formats de message, des règles, une syntaxe et une sémantique bien définis, etc. Cela signifie que même si l'appareil prend en charge un protocole spécifique, il peut communiquer avec n'importe quel autre appareil. sur le net.

image
De TCP / IP vs OSI: quelle est la différence entre les deux modèles?

Les systèmes d'exploitation prennent généralement en charge les protocoles réseau, tels que HTTP, prêts à l'emploi, ce qui explique pourquoi nous n'avons pas besoin d'installer explicitement de logiciel supplémentaire pour accéder à Internet. La plupart des protocoles réseau prennent en charge une connexion ouverte entre deux appareils, ce qui leur permet de transférer des données dans les deux sens.

Le HTTP sur lequel le réseau s'exécute est différent. Il est connu sous le nom de protocole sans connexion car il est basé sur un mode de fonctionnement demande / réponse. Les navigateurs Web envoient au serveur des demandes d'images, de polices, de contenu, etc., mais une fois la demande terminée, la connexion entre le navigateur et le serveur est déconnectée.

image

Serveurs et clients


Le terme serveur peut être un peu déroutant pour les personnes qui débutent dans l'industrie pour la première fois, car il peut désigner à la fois le matériel (ordinateurs physiques qui hébergent tous les fichiers et logiciels requis par les sites Web) et le logiciel (un programme qui permet aux utilisateurs d'accéder à ces fichiers en ligne).

Aujourd'hui, nous allons parler du côté logiciel des choses. Mais d'abord, quelques définitions. L'URL signifie Universal Resource Locator et se compose de 3 parties: protocole , serveur et fichier demandé .

image
Structure d'URL

Le protocole HTTP définit plusieurs méthodes que le navigateur peut utiliser pour demander au serveur d'effectuer un tas d'actions différentes, dont les plus courantes sont GET et POST. Lorsqu'un utilisateur clique sur un lien ou entre une URL dans la barre d'adresse, le navigateur envoie une demande GET au serveur pour récupérer la ressource spécifiée dans l'URL.

Le serveur doit savoir comment traiter cette demande HTTP afin de recevoir le fichier correct, puis le renvoyer au navigateur qui l'a demandé. Le logiciel de serveur Web le plus populaire qui gère cela est Apache et NGINX .

image
Les serveurs Web traitent les demandes entrantes et y répondent en conséquence

Les deux sont des progiciels open source complets qui incluent des fonctionnalités telles que les schémas d'authentification, la réécriture d'URL, la journalisation et le proxy, pour n'en nommer que quelques-uns. Apache et NGINX sont écrits en C. Techniquement, vous pouvez écrire un serveur Web dans n'importe quelle langue. Python , golang.org/pkg/net/http , Ruby , cette liste peut durer un certain temps. C’est juste que certaines langues font certaines choses mieux que d’autres.

Création d'un serveur HTTP avec Node.js


Node.js est un runtime Javascript construit sur le moteur Javascript Chrome V8 . Il est livré avec le module http , qui fournit un ensemble de fonctions et de classes pour la construction d'un serveur HTTP.

Pour ce serveur HTTP de base, nous utiliserons également le système de fichiers , le chemin et l' URL , qui sont des modules natifs Node.js.

Commencez par importer les modules requis.

const http = require('http') //   HTTP-  Node.js const fs = require('fs') //      const path = require('path') //        const url = require('url') //     URL 

Nous allons également créer un dictionnaire de types MIME afin de pouvoir attribuer le type MIME approprié à la ressource demandée en fonction de son extension. Une liste complète des types MIME se trouve dans Internet Assigned Numbers Authority .

 const mimeTypes = { '.html': 'text/html', '.js': 'text/javascript', '.css': 'text/css', '.ico': 'image/x-icon', '.png': 'image/png', '.jpg': 'image/jpeg', '.gif': 'image/gif', '.svg': 'image/svg+xml', '.json': 'application/json', '.woff': 'font/woff', '.woff2': 'font/woff2' } 

Nous pouvons maintenant créer un serveur HTTP avec la fonction http.createServer() , qui retournera une nouvelle instance de http.Server .

 const server = http.createServer() 

Nous passerons la fonction de gestionnaire de createServer() à createServer() avec les objets request et response. Cette fonction est appelée une fois à chaque fois qu'une requête HTTP arrive sur le serveur.

 server.on('request', (req, res) => { //     }) 

Le serveur est démarré en appelant la méthode listen de l'objet server avec le numéro de port sur lequel nous voulons que le serveur écoute, par exemple 5000 .

 server.listen(5000) 

L'objet de request est une instance de IncomingMessage et nous permet d'accéder à toutes les informations sur la demande, telles que l'état de la réponse, les en-têtes et les données.

L'objet de response est une instance de ServerResponse , qui est un flux inscriptible et fournit de nombreuses méthodes pour renvoyer des données au client.

Dans le gestionnaire de requêtes, nous voulons effectuer les opérations suivantes:

  • Analyser la demande entrante et la traiter sans extensions

     const parsedUrl = new URL(req.url, 'https://node-http.glitch.me/') let pathName = parsedUrl.pathname let ext = path.extname(pathName) //   URL    '/',   '/' //      URL    'Location' if (pathName !== '/' && pathName[pathName.length - 1] === '/') { res.writeHead(302, {'Location': pathName.slice(0, -1)}) res.end() return } //     ,  index.html //     «.html»       if (pathName === '/') { ext = '.html' pathName = '/index.html' } else if (!ext) { ext = '.html' pathName += ext } 

  • Effectuer quelques vérifications élémentaires pour déterminer si la ressource demandée existe et répondre en conséquence

     //     ,       const filePath = path.join(process.cwd(), '/public', pathName) // ,       fs.exists(filePath, function (exists, err) { //     ,  404 Not Found if (!exists || !mimeTypes[ext]) { console.log('  : ' + pathName) res.writeHead(404, {'Content-Type': 'text/plain'}) res.write('404 Not Found') res.end() return } //        200 OK, //       res.writeHead(200, {'Content-Type': mimeTypes[ext]}) //        const fileStream = fs.createReadStream(filePath) fileStream.pipe(res) }) 


Tout le code est hébergé sur Glitch, et vous pouvez remixer le projet si vous le souhaitez.

https://glitch.com/edit/#!/node-http

Création d'un serveur HTTP avec des frameworks Node.js


Les frameworks Node.js tels qu'Express , Koa.js et Hapi.js sont livrés avec diverses fonctions middleware utiles, en plus de nombreuses autres fonctionnalités pratiques qui évitent aux développeurs d'avoir à écrire pour eux-mêmes.

Personnellement, je pense qu'il vaut mieux d'abord apprendre les bases sans framework, juste pour comprendre ce qui se passe sous le capot, puis devenir fou avec n'importe quel framework que vous aimez.

Express a son propre plugin intégré pour servir des fichiers statiques, donc le code requis pour effectuer les mêmes actions que dans son propre Node.js est beaucoup plus court.

 const express = require('express') const app = express() //         app.use(express.static('public')) //  index.html,      //     res.sendFile() app.get('/', (req, res) => { res.sendFile(__dirname + '/public/index.html') }) app.listen(5000) 

Koa.js n'a pas de plugin similaire à l'intérieur de son noyau, donc tout plugin requis doit être installé séparément. La dernière version de Koa.js utilise des fonctions asynchrones en faveur des rappels. Vous pouvez utiliser le plugin koa-static pour servir des fichiers statiques.

 const serve = require('koa-static') const koa = require('koa') const app = new koa() //         //   koa-static    index.html    app.use(serve(__dirname + '/public')) app.listen(5000) 

Hapi.js prend en charge la personnalisation et s'articule autour de la personnalisation de l'objet server . Il utilise des plugins pour étendre des fonctionnalités telles que le routage, l'authentification, etc. Pour servir des fichiers statiques, nous avons besoin d'un plugin appelé inert .

 const path = require('path') const hapi = require('hapi') const inert = require('inert') //        const server = new hapi.Server({ port: 5000, routes: { files: { relativeTo: path.join(__dirname, 'public') } } }) const init = async () => { // server.register()      await server.register(inert) // inert     //       server.route({ method: 'GET', path: '/{param*}', handler: { directory: { path: '.', redirectToSlash: true, index: true } } }) await server.start() } init() 

Chacune de ces plateformes a ses avantages et ses inconvénients, et elles seront plus évidentes pour les applications plus grandes, et pas seulement pour servir une seule page HTML. Le choix de la structure dépendra grandement des exigences réelles du projet sur lequel vous travaillez.

Achèvement


Si le côté réseau des choses a toujours été une boîte noire pour vous, j'espère que cet article pourra servir d'introduction utile au protocole qui fournit le réseau. Je recommande également fortement de lire la documentation de l'API Node.js , qui est très bien écrite et très utile pour tout débutant sur Node.js en général.

Source: https://habr.com/ru/post/fr435970/


All Articles