Creación de una API Express de Node.js para convertir Markdown a HTML
Publicado: 2022-03-10Markdown es un lenguaje de marcado de texto ligero que permite convertir el texto marcado a varios formatos. El objetivo original de crear Markdown era permitir que las personas "escribieran utilizando un formato de texto sin formato fácil de leer y escribir" y, opcionalmente, convertirlo a XHTML estructuralmente válido (o HTML). Actualmente, con WordPress compatible con Markdown, el formato se ha vuelto aún más utilizado.
El propósito de escribir el artículo es mostrarle cómo usar Node.js y el marco Express para crear un punto final de API. El contexto en el que aprenderemos esto es creando una aplicación que convierta la sintaxis de Markdown a HTML. También agregaremos un mecanismo de autenticación a la API para evitar el mal uso de nuestra aplicación.
Una aplicación Markdown Node.js
Nuestra diminuta aplicación, a la que llamaremos 'Markdown Converter', nos permitirá publicar texto con estilo Markdown y recuperar una versión HTML. La aplicación se creará utilizando el marco Node.js Express y admitirá la autenticación para las solicitudes de conversión.
Construiremos la aplicación en pequeñas etapas: inicialmente crearemos un andamio usando Express y luego agregaremos varias características como la autenticación a medida que avanzamos. Entonces, comencemos con la etapa inicial de creación de la aplicación mediante la creación de un andamio.
Etapa 1: Instalación de Express
Suponiendo que ya instaló Node.js en su sistema, cree un directorio para almacenar su aplicación (llamémoslo " markdown-api
") y cambie a ese directorio:
$ mkdir markdown-api $ cd markdown-api
Utilice el comando npm init para crear un archivo package.json para su aplicación. Este comando le solicita una serie de cosas, como el nombre y la versión de su aplicación.
Por ahora, simplemente presione Enter para aceptar los valores predeterminados para la mayoría de ellos. He usado el archivo de punto de entrada predeterminado como index.js , pero puede probar app.js u otro según sus preferencias.
Ahora instale Express en el directorio markdown-api
y guárdelo en la lista de dependencias:
$ npm install express --save
Cree un archivo index.js en el directorio actual ( markdown-api
) y agregue el siguiente código para probar si Express Framework está instalado correctamente:
Const express = require('express'); var app = express(); app.get('/', function(req, res){ res.send('Hello World!'); }); app.listen(3000);
Ahora busque la URL https://localhost:3000
para comprobar si el archivo de prueba funciona correctamente. Si todo está en orden, veremos un Hello World!' saludo en el navegador y podemos proceder a construir una API base para convertir Markdown a HTML.
Etapa 2: Creación de una API base
El propósito principal de nuestra API será convertir texto en una sintaxis Markdown a HTML. La API tendrá dos puntos finales:
-
/login
-
/convert
El punto final de login
de sesión permitirá que la aplicación autentique solicitudes válidas, mientras que el punto final de convert
convertirá (obviamente) Markdown a HTML.
A continuación se muestra el código API base para llamar a los dos puntos finales. La llamada de inicio de login
solo devuelve una cadena "Autenticada", mientras que la llamada de convert
devuelve cualquier contenido de Markdown que haya enviado a la aplicación. El método de inicio simplemente devuelve un '¡Hola mundo!' cuerda.
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"); });
Usamos el middleware body-parser
para facilitar el análisis de las solicitudes entrantes a las aplicaciones. El middleware pondrá a su disposición todas las solicitudes entrantes bajo la propiedad req.body
. Puede prescindir del middleware adicional, pero agregarlo hace que sea mucho más fácil analizar varios parámetros de solicitudes entrantes.
Puede instalar body-parser
simplemente usando npm:
$ npm install body-parser
Ahora que tenemos nuestras funciones de código auxiliar ficticio en su lugar, usaremos Postman para probar lo mismo. Comencemos primero con una breve descripción general de Postman.
Descripción general del cartero
Postman es una herramienta de desarrollo de API que facilita la creación, modificación y prueba de puntos finales de API desde un navegador o mediante la descarga de una aplicación de escritorio (la versión del navegador ahora está obsoleta). Tiene la capacidad de realizar varios tipos de solicitudes HTTP, es decir, GET, POST, PUT, PATCH. Está disponible para Windows, macOS y Linux.
Aquí hay una muestra de la interfaz de Postman:

Para consultar un punto final de API, deberá realizar los siguientes pasos:
- Ingrese la URL que desea consultar en la barra de URL en la sección superior;
- Seleccione el método HTTP a la izquierda de la barra de URL para enviar la solicitud;
- Haga clic en el botón 'Enviar'.
Postman luego enviará la solicitud a la aplicación, recuperará las respuestas y las mostrará en la ventana inferior. Este es el mecanismo básico sobre cómo utilizar la herramienta Postman. En nuestra aplicación también tendremos que añadir otros parámetros a la petición, que se describirán en los siguientes apartados.
usando cartero
Ahora que hemos visto una descripción general de Postman, avancemos en su uso para nuestra aplicación.
Inicie su aplicación markdown-api
desde la línea de comandos:
$ node index.js
Para probar el código API base, hacemos llamadas API a la aplicación desde Postman. Tenga en cuenta que usamos el método POST para pasar el texto a convertir a la aplicación.
Actualmente, la aplicación acepta el contenido de Markdown para convertirlo a través del parámetro POST de content
. Esto lo pasamos como un formato codificado de URL. Actualmente, la aplicación devuelve la cadena textualmente en formato JSON, con el primer campo siempre devolviendo la cadena de markdown
y el segundo campo devolviendo el texto convertido. Más tarde, cuando agreguemos el código de procesamiento de Markdown, devolverá el texto convertido.
Etapa 3: Agregando Markdown Converter
Con el andamio de la aplicación ahora creado, podemos buscar en la biblioteca Showdown
JavaScript que usaremos para convertir Markdown a HTML. Showdown es un convertidor bidireccional de Markdown a HTML escrito en JavaScript que le permite convertir Markdown a HTML y viceversa.

Instale el paquete usando npm:
$ npm install showdown
Después de agregar el código de enfrentamiento requerido al andamio, obtenemos el siguiente resultado:
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"); });
El código del convertidor principal está en el punto final /convert
como se extrae y se muestra a continuación. Esto convertirá cualquier texto de Markdown que publique en una versión HTML y lo devolverá como un documento JSON.
... } else { text = req.body.content; html = converter.makeHtml(text); res.json(["markdown", html]); }
El método que realiza la conversión es converter.makeHtml(text)
. Podemos configurar varias opciones para la conversión de Markdown usando el método setOption
con el siguiente formato:
converter.setOption('optionKey', 'value');
Entonces, por ejemplo, podemos configurar una opción para insertar y vincular automáticamente una URL específica sin ningún marcado.
converter.setOption('simplifiedAutoLink', 'true');
Como en el ejemplo de Postman, si pasamos una cadena simple (como Google home https://www.google.com/
) a la aplicación, devolverá la siguiente cadena si la función simplifiedAutoLink
está habilitada:

<p>Google home <a href="https://www.google.com/">https://www.google.com/</a></p>
Sin la opción, tendremos que agregar información de marcado para lograr los mismos resultados:
Google home <https://www.google.com/>
Hay muchas opciones para modificar cómo se procesa el Markdown. Se puede encontrar una lista completa en el sitio web de Showdown.
Así que ahora tenemos un convertidor de Markdown a HTML en funcionamiento con un solo punto final. Avancemos más y agreguemos autenticación para tener una aplicación.
Etapa 4: Adición de autenticación de API mediante Passport
Exponer la API de su aplicación al mundo exterior sin la autenticación adecuada alentará a los usuarios a consultar su punto final de API sin restricciones. Esto invitará a elementos sin escrúpulos a hacer un mal uso de su API y también sobrecargará su servidor con solicitudes no moderadas. Para mitigar esto, tenemos que agregar un mecanismo de autenticación adecuado.
Usaremos el paquete Passport para agregar autenticación a nuestra aplicación. Al igual que el middleware body-parser
que encontramos anteriormente, Passport es un middleware de autenticación para Node.js. La razón por la que usaremos Passport es que tiene una variedad de mecanismos de autenticación con los que trabajar (nombre de usuario y contraseña, Facebook, Twitter, etc.), lo que le brinda al usuario la flexibilidad de elegir un mecanismo en particular. Un middleware de Passport se puede colocar fácilmente en cualquier aplicación Express sin cambiar mucho el código.
Instale el paquete usando npm.
$ npm install passport
También usaremos la estrategia local
, que se explicará más adelante, para la autenticación. Así que instálalo también.
$ npm install passport-local
También deberá agregar el módulo de codificación y decodificación JWT (JSON Web Token) para Node.js que utiliza Passport:
$ npm install jwt-simple
Estrategias en Pasaporte
Passport utiliza el concepto de estrategias para autenticar solicitudes. Las estrategias son varios métodos que le permiten autenticar solicitudes y pueden variar desde el caso simple como verificar las credenciales de nombre de usuario y contraseña, la autenticación mediante OAuth (Facebook o Twitter) o mediante OpenID. Antes de autenticar las solicitudes, se debe configurar la estrategia utilizada por una aplicación.
En nuestra aplicación, utilizaremos un esquema simple de autenticación de nombre de usuario y contraseña, ya que es simple de entender y codificar. Actualmente, Passport admite más de 300 estrategias que se pueden encontrar aquí.
Aunque el diseño de Passport pueda parecer complicado, la implementación en código es muy sencilla. Aquí hay un ejemplo que muestra cómo nuestro punto final /convert
está decorado para la autenticación. Como verá, agregar autenticación a un método es bastante 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 }) });
Ahora, junto con la cadena Markdown a convertir, también tenemos que enviar un nombre de usuario y una contraseña. Esto se verificará con el nombre de usuario y la contraseña de nuestra aplicación y se verificará. Como estamos utilizando una estrategia local para la autenticación, las credenciales se almacenan en el propio código.
Aunque esto puede sonar como una pesadilla de seguridad, para las aplicaciones de demostración es lo suficientemente bueno. Esto también facilita la comprensión del proceso de autenticación en nuestro ejemplo. Por cierto, un método de seguridad común utilizado es almacenar credenciales en variables de entorno. Aún así, muchas personas pueden no estar de acuerdo con este método, pero lo encuentro relativamente seguro.
El ejemplo completo con autenticación se muestra a continuación.
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"); });
A continuación se muestra una sesión de Postman que muestra la conversión con autenticación añadida.

Aquí podemos ver que tenemos una cadena HTML convertida adecuada a partir de una sintaxis de Markdown. Aunque solo hemos solicitado convertir una sola línea de Markdown, la API puede convertir una mayor cantidad de texto.
Esto concluye nuestra breve incursión en la creación de un punto final de API con Node.js y Express. La creación de API es un tema complejo y hay matices más sutiles que debe tener en cuenta al crear una, para lo cual, lamentablemente, no tenemos tiempo aquí, pero tal vez lo cubriremos en artículos futuros.
Accediendo a nuestra API desde otra aplicación
Ahora que hemos creado una API, podemos crear un pequeño script de Node.js que le mostrará cómo se puede acceder a la API. Para nuestro ejemplo, necesitaremos instalar el paquete request
npm que proporciona una forma sencilla de realizar solicitudes HTTP. (Lo más probable es que ya tenga esto instalado).
$ npm install request --save
El código de ejemplo para enviar una solicitud a nuestra API y obtener la respuesta se proporciona a continuación. Como puede ver, el paquete de request
simplifica considerablemente el asunto. El descuento que se va a convertir está en la variable textToConvert
.
Antes de ejecutar el siguiente script, asegúrese de que la aplicación API que creamos anteriormente ya se esté ejecutando. Ejecute el siguiente script en otra ventana de comandos.
Nota : estamos usando el signo (back-tick)
para abarcar varias líneas de JavaScript para la variable textToConvert
. Esto no es una comilla simple.
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)); });
Cuando hacemos una solicitud POST a nuestra API, proporcionamos el texto Markdown para convertirlo junto con las credenciales. Si proporcionamos las credenciales incorrectas, recibiremos un mensaje de error.
{ success: false, message: { name: 'AuthenticationError', message: 'Unauthorized', status: 401 } }
Para una solicitud autorizada correctamente, el Markdown de muestra anterior se convertirá en lo siguiente:
[ '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>` ]
Aunque hemos codificado el Markdown aquí, el texto puede provenir de otras fuentes: archivos, formularios web, etc. El proceso de solicitud sigue siendo el mismo.
Tenga en cuenta que estamos enviando la solicitud como un tipo de contenido de application/json
; necesitamos codificar el cuerpo usando json, de ahí la llamada a la función JSON.stringify
. Como puede ver, se necesita un ejemplo muy pequeño para probar o aplicar la API.
Conclusión
En este artículo, nos embarcamos en un tutorial con el objetivo de aprender cómo usar Node, js y el marco Express para construir un punto final de API. En lugar de crear una aplicación ficticia sin propósito, decidimos crear una API que convierte la sintaxis de Markdown en HTML, que ancla o aprende en un contexto útil. En el camino, agregamos autenticación a nuestro punto final de API y también vimos formas de probar nuestro punto final de aplicación usando Postman.