Construire une API Node.js Express pour convertir Markdown en HTML

Publié: 2022-03-10
Résumé rapide ↬ Apprenez à utiliser Node.js et le framework Express afin de créer un point de terminaison API - dans le contexte de la création d'une application qui convertit la syntaxe Markdown en HTML.

Markdown est un langage de balisage de texte léger qui permet de convertir le texte marqué en différents formats. L'objectif initial de la création de Markdown était de permettre aux gens "d'écrire en utilisant un format de texte brut facile à lire et à écrire" et de le convertir éventuellement en XHTML (ou HTML) structurellement valide. Actuellement, avec WordPress prenant en charge Markdown, le format est devenu encore plus largement utilisé.

Le but de la rédaction de l'article est de vous montrer comment utiliser Node.js et le framework Express pour créer un point de terminaison API. Le contexte dans lequel nous allons apprendre cela est en construisant une application qui convertit la syntaxe Markdown en HTML. Nous ajouterons également un mécanisme d'authentification à l'API afin d'éviter toute utilisation abusive de notre application.

Une application Markdown Node.js

Notre toute petite application, que nous appellerons 'Markdown Converter', nous permettra de poster du texte de style Markdown et d'en récupérer une version HTML. L'application sera créée à l'aide du framework Node.js Express et prendra en charge l'authentification pour les demandes de conversion.

Nous allons créer l'application par petites étapes - en créant d'abord un échafaudage à l'aide d'Express, puis en ajoutant diverses fonctionnalités telles que l'authentification au fur et à mesure. Commençons donc par l'étape initiale de construction de l'application en créant un échafaudage.

Plus après saut! Continuez à lire ci-dessous ↓

Étape 1 : Installation d'Express

En supposant que vous avez déjà installé Node.js sur votre système, créez un répertoire pour contenir votre application (appelons-le « markdown-api ») et basculez vers ce répertoire :

 $ mkdir markdown-api $ cd markdown-api

Utilisez la commande npm init pour créer un fichier package.json pour votre application. Cette commande vous demande un certain nombre de choses comme le nom et la version de votre application.

Pour l'instant, appuyez simplement sur Entrée pour accepter les valeurs par défaut pour la plupart d'entre eux. J'ai utilisé le fichier de point d'entrée par défaut comme index.js , mais vous pouvez essayer app.js ou un autre selon vos préférences.

Installez maintenant Express dans le répertoire markdown-api et enregistrez-le dans la liste des dépendances :

 $ npm install express --save

Créez un fichier index.js dans le répertoire courant ( markdown-api ) et ajoutez le code suivant pour tester si le framework Express est correctement installé :

 Const express = require('express'); var app = express(); app.get('/', function(req, res){ res.send('Hello World!'); }); app.listen(3000);

Accédez maintenant à l'URL https://localhost:3000 pour vérifier si le fichier de test fonctionne correctement. Si tout est en ordre, nous verrons un Hello World!' salutation dans le navigateur et nous pouvons procéder à la création d'une API de base pour convertir Markdown en HTML.

Étape 2 : Créer une API de base

L'objectif principal de notre API sera de convertir du texte dans une syntaxe Markdown en HTML. L'API aura deux points de terminaison :

  • /login
  • /convert

Le point de terminaison de login permettra à l'application d'authentifier les demandes valides tandis que le point de terminaison de conversion convert (évidemment) Markdown en HTML.

Vous trouverez ci-dessous le code API de base pour appeler les deux points de terminaison. L'appel de login renvoie simplement une chaîne "Authentifiée", tandis que l'appel de convert renvoie le contenu Markdown que vous avez soumis à l'application. La méthode home renvoie simplement un "Hello World!" chaîne de caractères.

 const express = require("express"); const bodyParser = require('body-parser'); var app = express(); app.use(bodyParser.urlencoded({ extended: true })); app.use(bodyParser.json()); app.get('/', function(req, res){ res.send('Hello World!'); }); app.post('/login', function(req, res) { res.send("Authenticated"); }, ); app.post("/convert", function(req, res, next) { console.log(req.body); if(typeof req.body.content == 'undefined' || req.body.content == null) { res.json(["error", "No data found"]); } else { res.json(["markdown", req.body.content]); } }); app.listen(3000, function() { console.log("Server running on port 3000"); });

Nous utilisons le middleware body-parser pour faciliter l'analyse des requêtes entrantes vers les applications. Le middleware mettra toutes les requêtes entrantes à votre disposition sous la propriété req.body . Vous pouvez vous passer du middleware supplémentaire, mais son ajout facilite grandement l'analyse des différents paramètres de requête entrants.

Vous pouvez installer body-parser en utilisant simplement npm :

 $ npm install body-parser

Maintenant que nos fonctions factices sont en place, nous allons utiliser Postman pour tester la même chose. Commençons d'abord par un bref aperçu de Postman.

Présentation de Postman

Postman est un outil de développement d'API qui facilite la création, la modification et le test des points de terminaison d'API à partir d'un navigateur ou en téléchargeant une application de bureau (la version du navigateur est désormais obsolète). Il a la capacité de faire différents types de requêtes HTTP, c'est-à-dire GET, POST, PUT, PATCH. Il est disponible pour Windows, macOS et Linux.

Voici un avant-goût de l'interface de Postman :

Interface facteur
( Grand aperçu )

Pour interroger un point de terminaison d'API, vous devez effectuer les étapes suivantes :

  1. Entrez l'URL que vous souhaitez interroger dans la barre d'URL dans la section supérieure ;
  2. Sélectionnez la méthode HTTP à gauche de la barre d'URL pour envoyer la requête ;
  3. Cliquez sur le bouton 'Envoyer'.

Postman enverra alors la demande à l'application, récupérera les réponses et l'affichera dans la fenêtre inférieure. C'est le mécanisme de base sur la façon d'utiliser l'outil Postman. Dans notre application, nous devrons également ajouter d'autres paramètres à la requête, qui seront décrits dans les sections suivantes.

Utilisation du facteur

Maintenant que nous avons vu un aperçu de Postman, continuons à l'utiliser pour notre application.

Démarrez votre application markdown-api à partir de la ligne de commande :

 $ node index.js

Pour tester le code API de base, nous effectuons des appels API à l'application depuis Postman. Notez que nous utilisons la méthode POST pour passer le texte à convertir à l'application.

L'application accepte actuellement le contenu Markdown à convertir via le paramètre POST de content . Ce que nous transmettons comme format encodé d'URL. L'application, actuellement, renvoie la chaîne textuellement dans un format JSON - avec le premier champ renvoyant toujours la chaîne markdown et le second champ renvoyant le texte converti. Plus tard, lorsque nous ajouterons le code de traitement Markdown, il renverra le texte converti.

Étape 3 : Ajout du convertisseur Markdown

Avec l'échafaudage d'application maintenant construit, nous pouvons examiner la bibliothèque JavaScript Showdown que nous utiliserons pour convertir Markdown en HTML. Showdown est un convertisseur bidirectionnel Markdown vers HTML écrit en JavaScript qui vous permet de convertir Markdown en HTML et inversement.

Test avec Postman
( Grand aperçu )

Installez le package à l'aide de npm :

 $ npm install showdown

Après avoir ajouté le code de démonstration requis à l'échafaudage, nous obtenons le résultat suivant :

 const express = require("express"); const bodyParser = require('body-parser'); const showdown = require('showdown'); var app = express(); app.use(bodyParser.urlencoded({ extended: true })); app.use(bodyParser.json()); converter = new showdown.Converter(); app.get('/', function(req, res){ res.send('Hello World!'); }); app.post('/login', function(req, res) { res.send("Authenticated"); }, ); app.post("/convert", function(req, res, next) { if(typeof req.body.content == 'undefined' || req.body.content == null) { res.json(["error", "No data found"]); } else { text = req.body.content; html = converter.makeHtml(text); res.json(["markdown", html]); } }); app.listen(3000, function() { console.log("Server running on port 3000"); });

Le code du convertisseur principal se trouve dans le point de terminaison /convert tel qu'extrait et illustré ci-dessous. Cela convertira tout texte Markdown que vous publiez en une version HTML et le renverra sous forme de document JSON.

 ... } else { text = req.body.content; html = converter.makeHtml(text); res.json(["markdown", html]); }

La méthode qui effectue la conversion est converter.makeHtml(text) . Nous pouvons définir diverses options pour la conversion Markdown à l'aide de la méthode setOption au format suivant :

 converter.setOption('optionKey', 'value');

Ainsi, par exemple, nous pouvons définir une option pour insérer et lier automatiquement une URL spécifiée sans aucun balisage.

 converter.setOption('simplifiedAutoLink', 'true');

Comme dans l'exemple Postman, si nous transmettons une chaîne simple (telle que Google home https://www.google.com/ ) à l'application, elle renverra la chaîne suivante si le lien automatique simplifiedAutoLink est activé :

 <p>Google home <a href="https://www.google.com/">https://www.google.com/</a></p>

Sans l'option, nous devrons ajouter des informations de balisage pour obtenir les mêmes résultats :

 Google home <https://www.google.com/>

Il existe de nombreuses options pour modifier la façon dont le Markdown est traité. Une liste complète peut être trouvée sur le site Web de Showdown.

Nous avons donc maintenant un convertisseur Markdown-to-HTML fonctionnel avec un seul point de terminaison. Allons plus loin et ajoutons l'authentification pour avoir une application.

Étape 4 : Ajouter l'authentification API à l'aide de Passport

L'exposition de votre API d'application au monde extérieur sans authentification appropriée encouragera les utilisateurs à interroger votre point de terminaison d'API sans aucune restriction. Cela invitera des éléments peu scrupuleux à abuser de votre API et alourdira également votre serveur avec des requêtes non modérées. Pour atténuer cela, nous devons ajouter un mécanisme d'authentification approprié.

Nous utiliserons le package Passport pour ajouter l'authentification à notre application. Tout comme le middleware body-parser que nous avons rencontré précédemment, Passport est un middleware d'authentification pour Node.js. La raison pour laquelle nous utiliserons Passport est qu'il dispose d'une variété de mécanismes d'authentification avec lesquels travailler (nom d'utilisateur et mot de passe, Facebook, Twitter, etc.), ce qui donne à l'utilisateur la flexibilité de choisir un mécanisme particulier. Un middleware Passport peut être facilement inséré dans n'importe quelle application Express sans modifier beaucoup de code.

Installez le paquet en utilisant npm.

 $ npm install passport

Nous utiliserons également la stratégie local , qui sera expliquée plus tard, pour l'authentification. Alors installez-le aussi.

 $ npm install passport-local

Vous devrez également ajouter le module d'encodage et de décodage JWT (JSON Web Token) pour Node.js qui est utilisé par Passport :

 $ npm install jwt-simple

Stratégies de passeport

Passport utilise le concept de stratégies pour authentifier les demandes. Les stratégies sont diverses méthodes qui vous permettent d'authentifier les demandes et peuvent aller du cas simple à la vérification des informations d'identification du nom d'utilisateur et du mot de passe, à l'authentification à l'aide d'OAuth (Facebook ou Twitter) ou à l'aide d'OpenID. Avant d'authentifier les requêtes, la stratégie utilisée par une application doit être configurée.

Dans notre application, nous utiliserons un schéma d'authentification simple par nom d'utilisateur et mot de passe, car il est simple à comprendre et à coder. Actuellement, Passport prend en charge plus de 300 stratégies qui peuvent être trouvées ici.

Bien que la conception de Passport puisse sembler compliquée, l'implémentation en code est très simple. Voici un exemple qui montre comment notre point de terminaison /convert est décoré pour l'authentification. Comme vous le verrez, ajouter une authentification à une méthode est assez simple.

 app.post("/convert", passport.authenticate('local',{ session: false, failWithError: true }), function(req, res, next) { // If this function gets called, authentication was successful. // Also check if no content is sent if(typeof req.body.content == 'undefined' || req.body.content == null) { res.json(["error", "No data found"]); } else { text = req.body.content; html = converter.makeHtml(text); res.json(["markdown", html]); }}, // Return a 'Unauthorized' message back if authentication failed. function(err, req, res, next) { return res.status(401).send({ success: false, message: err }) });

Maintenant, avec la chaîne Markdown à convertir, nous devons également envoyer un nom d'utilisateur et un mot de passe. Cela sera vérifié avec notre nom d'utilisateur et mot de passe d'application et vérifié. Comme nous utilisons une stratégie locale pour l'authentification, les informations d'identification sont stockées dans le code lui-même.

Bien que cela puisse ressembler à un cauchemar pour la sécurité, cela suffit pour les applications de démonstration. Cela facilite également la compréhension du processus d'authentification dans notre exemple. Incidemment, une méthode de sécurité couramment utilisée consiste à stocker les informations d'identification dans des variables d'environnement. Pourtant, beaucoup de gens peuvent ne pas être d'accord avec cette méthode, mais je trouve cela relativement sûr.

L'exemple complet avec authentification est présenté ci-dessous.

 const express = require("express"); const showdown = require('showdown'); const bodyParser = require('body-parser'); const passport = require('passport'); const jwt = require('jwt-simple'); const LocalStrategy = require('passport-local').Strategy; var app = express(); app.use(bodyParser.urlencoded({ extended: true })); app.use(bodyParser.json()); converter = new showdown.Converter(); const ADMIN = 'admin'; const ADMIN_PASSWORD = 'smagazine'; const SECRET = 'secret#4456'; passport.use(new LocalStrategy(function(username, password, done) { if (username === ADMIN && password === ADMIN_PASSWORD) { done(null, jwt.encode({ username }, SECRET)); return; } done(null, false); })); app.get('/', function(req, res){ res.send('Hello World!'); }); app.post('/login', passport.authenticate('local',{ session: false }), function(req, res) { // If this function gets called, authentication was successful. // Send a 'Authenticated' string back. res.send("Authenticated"); }); app.post("/convert", passport.authenticate('local',{ session: false, failWithError: true }), function(req, res, next) { // If this function gets called, authentication was successful. // Also check if no content is sent if(typeof req.body.content == 'undefined' || req.body.content == null) { res.json(["error", "No data found"]); } else { text = req.body.content; html = converter.makeHtml(text); res.json(["markdown", html]); }}, // Return a 'Unauthorized' message back if authentication failed. function(err, req, res, next) { return res.status(401).send({ success: false, message: err }) }); app.listen(3000, function() { console.log("Server running on port 3000"); });

Une session Postman qui affiche la conversion avec l'authentification ajoutée est illustrée ci-dessous.

Test final de l'application avec Postman
Test final de l'application avec Postman ( Grand aperçu )

Ici, nous pouvons voir que nous avons une chaîne HTML convertie appropriée à partir d'une syntaxe Markdown. Bien que nous n'ayons demandé de convertir qu'une seule ligne de Markdown, l'API peut convertir une plus grande quantité de texte.

Ceci conclut notre brève incursion dans la création d'un point de terminaison d'API à l'aide de Node.js et Express. La construction d'API est un sujet complexe et il y a des nuances plus fines dont vous devez être conscient lors de la construction d'une API, que nous n'avons malheureusement pas le temps d'aborder ici mais que nous aborderons peut-être dans de futurs articles.

Accéder à notre API depuis une autre application

Maintenant que nous avons construit une API, nous pouvons créer un petit script Node.js qui vous montrera comment accéder à l'API. Pour notre exemple, nous devrons installer le package request npm qui fournit un moyen simple de faire des requêtes HTTP. (Vous l'aurez probablement déjà installé.)

 $ npm install request --save

L'exemple de code pour envoyer une requête à notre API et obtenir la réponse est donné ci-dessous. Comme vous pouvez le voir, le package de request simplifie considérablement la question. La démarque à convertir se trouve dans la variable textToConvert .

Avant d'exécuter le script suivant, assurez-vous que l'application API que nous avons créée précédemment est déjà en cours d'exécution. Exécutez le script suivant dans une autre fenêtre de commande.

Remarque : Nous utilisons le signe (back-tick) pour couvrir plusieurs lignes JavaScript pour la variable textToConvert . Ce n'est pas une simple citation.

 var Request = require("request"); // Start of markdown var textToConvert = `Heading ======= ## Sub-heading Paragraphs are separated by a blank line. Two spaces at the end of a line produces a line break. Text attributes _italic_, **bold**, 'monospace'. A [link](https://example.com). Horizontal rule:`; // End of markdown Request.post({ "headers": { "content-type": "application/json" }, "url": "https://localhost:3000/convert", "body": JSON.stringify({ "content": textToConvert, "username": "admin", "password": "smagazine" }) }, function(error, response, body){ // If we got any connection error, bail out. if(error) { return console.log(error); } // Else display the converted text console.dir(JSON.parse(body)); });

Lorsque nous faisons une requête POST à ​​notre API, nous fournissons le texte Markdown à convertir avec les informations d'identification. Si nous fournissons les mauvaises informations d'identification, nous serons accueillis par un message d'erreur.

 { success: false, message: { name: 'AuthenticationError', message: 'Unauthorized', status: 401 } }

Pour une demande correctement autorisée, l'exemple de Markdown ci-dessus sera converti comme suit :

 [ 'markdown', `<h1>Heading</h1> <h2>Sub-heading</h2> <p>Paragraphs are separated by a blank line.</p> <p>Two spaces at the end of a line<br /> produces a line break.</p> <p>Text attributes <em>italic</em>, <strong>bold</strong>, 'monospace'. A <a href="https://example.com">link</a>. Horizontal rule:</p>` ]

Bien que nous ayons codé en dur le Markdown ici, le texte peut provenir de diverses autres sources - fichiers, formulaires Web, etc. Le processus de demande reste le même.

Notez que comme nous envoyons la demande en tant que type de contenu application/json ; nous devons encoder le corps en utilisant json, d'où l'appel de fonction JSON.stringify . Comme vous pouvez le voir, il faut un très petit exemple pour tester ou appliquer l'API.

Conclusion

Dans cet article, nous nous sommes lancés dans un didacticiel dans le but d'apprendre à utiliser Node, js et le framework Express pour créer un point de terminaison d'API. Plutôt que de créer une application factice sans but, nous avons décidé de créer une API qui convertit la syntaxe Markdown en HTML, qui ancre ou apprend dans un contexte utile. En cours de route, nous avons ajouté l'authentification à notre point de terminaison API, et nous avons également vu des moyens de tester notre point de terminaison d'application à l'aide de Postman.