Создание Node.js Express API для преобразования Markdown в HTML

Опубликовано: 2022-03-10
Краткое резюме ↬ Узнайте, как использовать Node.js и платформу Express для создания конечной точки API — в контексте создания приложения, которое преобразует синтаксис Markdown в HTML.

Markdown — это облегченный язык разметки текста, который позволяет преобразовывать выделенный текст в различные форматы. Первоначальная цель создания Markdown заключалась в том, чтобы позволить людям «писать, используя удобный для чтения и написания простой текстовый формат» и, при желании, преобразовывать его в структурно допустимый XHTML (или HTML). В настоящее время, когда WordPress поддерживает Markdown, этот формат стал еще более широко использоваться.

Цель написания статьи — показать вам, как использовать Node.js и платформу Express для создания конечной точки API. Контекст, в котором мы будем изучать это, заключается в создании приложения, которое преобразует синтаксис Markdown в HTML. Мы также добавим в API механизм аутентификации, чтобы предотвратить неправильное использование нашего приложения.

Приложение Markdown Node.js

Наше крошечное приложение, которое мы назовем «Markdown Converter», позволит нам публиковать текст в стиле Markdown и получать HTML-версию. Приложение будет создано с использованием платформы Node.js Express и будет поддерживать аутентификацию для запросов на конвертацию.

Мы будем создавать приложение небольшими этапами — сначала создадим каркас с помощью Express, а затем по мере продвижения будем добавлять различные функции, такие как аутентификация. Итак, давайте начнем с начального этапа сборки приложения, создав скаффолд.

Еще после прыжка! Продолжить чтение ниже ↓

Этап 1: Установка Express

Предполагая, что вы уже установили Node.js в своей системе, создайте каталог для хранения вашего приложения (назовем его « markdown-api ») и переключитесь в этот каталог:

 $ mkdir markdown-api $ cd markdown-api

Используйте команду npm init, чтобы создать файл package.json для вашего приложения. Эта команда запрашивает у вас ряд вещей, таких как имя и версия вашего приложения.

А пока просто нажмите Enter , чтобы принять значения по умолчанию для большинства из них. Я использовал файл точки входа по умолчанию как index.js , но вы можете попробовать app.js или что-то другое в зависимости от ваших предпочтений.

Теперь установите Express в каталог markdown-api и сохраните его в списке зависимостей:

 $ npm install express --save

Создайте файл index.js в текущем каталоге ( markdown-api ) и добавьте следующий код, чтобы проверить, правильно ли установлена ​​среда Express:

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

Теперь перейдите по URL-адресу https://localhost:3000 , чтобы проверить, правильно ли работает тестовый файл. Если все в порядке, мы увидим Hello World!» приветствие в браузере, и мы можем приступить к созданию базового API для преобразования Markdown в HTML.

Этап 2: Создание базового API

Основной целью нашего API будет преобразование текста в синтаксисе Markdown в HTML. API будет иметь две конечные точки:

  • /login
  • /convert

Конечная точка login позволит приложению аутентифицировать действительные запросы, в то время как конечная точка convert преобразует (очевидно) Markdown в HTML.

Ниже приведен базовый код API для вызова двух конечных точек. Вызов login просто возвращает строку «Аутентифицировано», а вызов convert возвращает любой контент Markdown, который вы отправили в приложение. Домашний метод просто возвращает «Hello World!» нить.

 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"); });

Мы используем промежуточное ПО body-parser , чтобы упростить анализ входящих запросов к приложениям. Промежуточное ПО сделает все входящие запросы доступными для вас в req.body . Вы можете обойтись без дополнительного промежуточного программного обеспечения, но его добавление значительно упрощает анализ различных параметров входящего запроса.

Вы можете установить body-parser , просто используя npm:

 $ npm install body-parser

Теперь, когда у нас есть фиктивные функции-заглушки, мы будем использовать Postman для их тестирования. Давайте сначала начнем с краткого обзора Postman.

Обзор почтальона

Postman — это инструмент разработки API, который позволяет легко создавать, изменять и тестировать конечные точки API из браузера или путем загрузки настольного приложения (версия для браузера в настоящее время устарела). Он может выполнять различные типы HTTP-запросов, например, GET, POST, PUT, PATCH. Он доступен для Windows, macOS и Linux.

Вот вкус интерфейса Postman:

Интерфейс почтальона
(Большой превью)

Чтобы запросить конечную точку API, вам необходимо выполнить следующие шаги:

  1. Введите URL-адрес, который вы хотите запросить, в строке URL-адреса в верхней части;
  2. Выберите метод HTTP слева от строки URL для отправки запроса;
  3. Нажмите кнопку «Отправить».

Затем Postman отправит запрос в приложение, получит все ответы и отобразит их в нижнем окне. Это основной механизм использования инструмента Postman. В нашем приложении нам также придется добавить в запрос другие параметры, которые будут описаны в следующих разделах.

Использование почтальона

Теперь, когда мы ознакомились с Postman, давайте перейдем к его использованию в нашем приложении.

Запустите приложение markdown-api из командной строки:

 $ node index.js

Чтобы протестировать базовый код API, мы делаем вызовы API к приложению из Postman. Обратите внимание, что мы используем метод POST для передачи текста для преобразования в приложение.

В настоящее время приложение принимает содержимое Markdown для преобразования с помощью параметра POST content . Это мы передаем как формат с кодировкой URL. В настоящее время приложение возвращает строку в формате JSON — первое поле всегда возвращает markdown строки, а второе — преобразованный текст. Позже, когда мы добавим код обработки Markdown, он вернет преобразованный текст.

Этап 3: Добавление конвертера Markdown

Теперь, когда каркас приложения построен, мы можем заглянуть в библиотеку Showdown JavaScript, которую мы будем использовать для преобразования Markdown в HTML. Showdown — это двунаправленный конвертер Markdown в HTML, написанный на JavaScript, который позволяет конвертировать Markdown в HTML и обратно.

Тестирование с почтальоном
(Большой превью)

Установите пакет с помощью npm:

 $ npm install showdown

После добавления в скаффолд требуемого кода вскрытия получаем следующий результат:

 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"); });

Основной код преобразователя находится в конечной точке /convert , как показано ниже. Это преобразует любой текст Markdown, который вы публикуете, в HTML-версию и возвращает его в виде документа JSON.

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

Метод, выполняющий преобразование, — converter.makeHtml(text) . Мы можем установить различные параметры преобразования Markdown, используя метод setOption в следующем формате:

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

Так, например, мы можем установить параметр для автоматической вставки и ссылки на указанный URL-адрес без какой-либо разметки.

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

Как и в примере с почтальоном, если мы передаем простую строку (например, Google home https://www.google.com/ ) в приложение, оно вернет следующую строку, если включено simplifiedAutoLink автосвязывание:

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

Без опции нам придется добавить информацию о разметке для достижения тех же результатов:

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

Существует множество вариантов изменения способа обработки Markdown. Полный список можно найти на сайте Showdown.

Итак, теперь у нас есть работающий конвертер Markdown в HTML с одной конечной точкой. Давайте двинемся дальше и добавим аутентификацию, чтобы иметь приложение.

Этап 4: Добавление аутентификации API с использованием паспорта

Предоставление API вашего приложения внешнему миру без надлежащей аутентификации побудит пользователей запрашивать вашу конечную точку API без каких-либо ограничений. Это приведет к тому, что недобросовестные элементы будут злоупотреблять вашим API, а также обременят ваш сервер немодерируемыми запросами. Чтобы смягчить это, мы должны добавить правильный механизм аутентификации.

Мы будем использовать пакет Passport для добавления аутентификации в наше приложение. Как и промежуточное ПО для body-parser , с которым мы сталкивались ранее, Passport — это промежуточное ПО для аутентификации для Node.js. Причина, по которой мы будем использовать Passport, заключается в том, что он имеет множество механизмов аутентификации для работы (имя пользователя и пароль, Facebook, Twitter и т. д.), что дает пользователю гибкость при выборе конкретного механизма. Промежуточное программное обеспечение Passport можно легко добавить в любое приложение Express без особого изменения кода.

Установите пакет с помощью npm.

 $ npm install passport

Мы также будем использовать local стратегию, которая будет объяснена позже, для аутентификации. Так что устанавливайте и его.

 $ npm install passport-local

Вам также потребуется добавить модуль кодирования и декодирования JWT (JSON Web Token) для Node.js, который используется Passport:

 $ npm install jwt-simple

Стратегии в паспорте

Passport использует концепцию стратегий для аутентификации запросов. Стратегии — это различные методы, которые позволяют вам аутентифицировать запросы и могут варьироваться от простого случая, такого как проверка учетных данных имени пользователя и пароля, аутентификация с использованием OAuth (Facebook или Twitter) или с использованием OpenID. Перед аутентификацией запросов необходимо настроить стратегию, используемую приложением.

В нашем приложении мы будем использовать простую схему аутентификации по имени пользователя и паролю, так как она проста для понимания и кодирования. В настоящее время Passport поддерживает более 300 стратегий, которые можно найти здесь.

Хотя дизайн Passport может показаться сложным, его реализация в коде очень проста. Вот пример, который показывает, как наша конечная точка /convert оформлена для аутентификации. Как вы увидите, добавить аутентификацию в метод достаточно просто.

 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 }) });

Теперь вместе со строкой Markdown, которую нужно преобразовать, мы также должны отправить имя пользователя и пароль. Это будет проверено с помощью имени пользователя и пароля нашего приложения и подтверждено. Поскольку мы используем локальную стратегию аутентификации, учетные данные хранятся в самом коде.

Хотя это может звучать как кошмар безопасности, для демонстрационных приложений этого достаточно. Это также упрощает понимание процесса аутентификации в нашем примере. Между прочим, распространенный метод обеспечения безопасности заключается в хранении учетных данных в переменных среды. Тем не менее, многие люди могут не согласиться с этим методом, но я считаю его относительно безопасным.

Полный пример с аутентификацией показан ниже.

 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"); });

Сессия Postman, которая показывает преобразование с добавленной аутентификацией, показана ниже.

Финальное тестирование приложения с Postman
Окончательное тестирование приложения с Postman (большой предварительный просмотр)

Здесь мы видим, что у нас есть правильная преобразованная строка HTML из синтаксиса Markdown. Хотя мы запросили преобразование только одной строки Markdown, API может преобразовать больший объем текста.

На этом мы завершаем наш краткий экскурс в создание конечной точки API с использованием Node.js и Express. Создание API — сложная тема, и есть более тонкие нюансы, о которых вы должны знать при его создании, и, к сожалению, у нас нет на это времени, но, возможно, мы рассмотрим их в следующих статьях.

Доступ к нашему API из другого приложения

Теперь, когда мы создали API, мы можем создать небольшой скрипт Node.js, который покажет вам, как можно получить доступ к API. В нашем примере нам нужно будет установить пакет request npm, который предоставляет простой способ выполнения HTTP-запросов. (Скорее всего, вы уже установили это.)

 $ npm install request --save

Ниже приведен пример кода для отправки запроса в наш API и получения ответа. Как видите, пакет request значительно упрощает дело. Преобразуемая уценка находится в переменной textToConvert .

Перед запуском следующего скрипта убедитесь, что созданное ранее приложение API уже запущено. Запустите следующий сценарий в другом командном окне.

Примечание . Мы используем знак (back-tick) , чтобы охватить несколько строк JavaScript для переменной textToConvert . Это не одинарная кавычка.

 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)); });

Когда мы делаем POST-запрос к нашему API, мы предоставляем текст Markdown для преобразования вместе с учетными данными. Если мы предоставим неправильные учетные данные, нас встретит сообщение об ошибке.

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

Для правильно авторизованного запроса приведенный выше образец Markdown будет преобразован в следующее:

 [ '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>` ]

Хотя мы жестко закодировали здесь Markdown, текст может поступать из различных других источников — файлов, веб-форм и т. д. Процесс запроса остается прежним.

Обратите внимание, что поскольку мы отправляем запрос как тип контента application/json ; нам нужно закодировать тело с помощью json, отсюда и вызов функции JSON.stringify . Как видите, для тестирования приложения API требуется очень маленький пример.

Заключение

В этой статье мы приступили к руководству с целью узнать, как использовать Node, js и платформу Express для создания конечной точки API. Вместо того, чтобы создавать какое-то фиктивное приложение без цели, мы решили создать API, который преобразует синтаксис Markdown в HTML, который привязывает или обучает в полезном контексте. Попутно мы добавили аутентификацию в нашу конечную точку API, а также увидели способы протестировать конечную точку нашего приложения с помощью Postman.