構建 Node.js Express API 以將 Markdown 轉換為 HTML
已發表: 2022-03-10Markdown 是一種輕量級的文本標記語言,允許將標記的文本轉換為各種格式。 創建 Markdown 的最初目標是讓人們“使用易於閱讀和易於編寫的純文本格式進行編寫”,並可選擇將其轉換為結構上有效的 XHTML(或 HTML)。 目前,隨著 WordPress 支持 Markdown,該格式已得到更廣泛的使用。
撰寫本文的目的是向您展示如何使用 Node.js 和 Express 框架來創建 API 端點。 我們將通過構建一個將 Markdown 語法轉換為 HTML 的應用程序來學習這一點。 我們還將向 API 添加身份驗證機制,以防止濫用我們的應用程序。
一個 Markdown Node.js 應用程序
我們稱為“Markdown 轉換器”的小型應用程序將使我們能夠發布 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或其他文件。
現在在markdown-api
目錄中安裝 Express 並將其保存在依賴項列表中:
$ npm install express --save
在當前目錄( markdown-api
)創建一個index.js文件,並添加以下代碼來測試 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
調用只返回一個“Authenticated”字符串,而convert
調用返回你提交給應用程序的任何 Markdown 內容。 home 方法只返回一個“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
屬性下使用所有傳入的請求。 您可以不使用額外的中間件,但添加它可以更輕鬆地解析各種傳入的請求參數。
您可以通過簡單地使用 npm 來安裝body-parser
:
$ npm install body-parser
現在我們已經有了我們的虛擬存根函數,我們將使用 Postman 來測試它。 讓我們首先從 Postman 的簡要概述開始。
郵遞員概述
Postman 是一種 API 開發工具,可以輕鬆地在瀏覽器中或通過下載桌面應用程序(瀏覽器版本現已棄用)來構建、修改和測試 API 端點。 它能夠發出各種類型的 HTTP 請求,即 GET、POST、PUT、PATCH。 它適用於 Windows、macOS 和 Linux。
下面是 Postman 的界面體驗:
要查詢 API 端點,您需要執行以下步驟:
- 在頂部的網址欄中輸入您要查詢的網址;
- 選擇 URL 欄左側的 HTTP 方法發送請求;
- 單擊“發送”按鈕。
Postman 會將請求發送到應用程序,檢索任何響應並將其顯示在下部窗口中。 這是如何使用 Postman 工具的基本機制。 在我們的應用程序中,我們還必須向請求中添加其他參數,這將在以下部分中進行介紹。
使用郵遞員
現在我們已經看到了 Postman 的概述,讓我們繼續在我們的應用程序中使用它。
從命令行啟動你的markdown-api
應用程序:
$ node index.js
為了測試基本 API 代碼,我們從 Postman 對應用程序進行 API 調用。 請注意,我們使用 POST 方法將要轉換的文本傳遞給應用程序。
應用程序目前接受 Markdown 內容通過content
POST 參數進行轉換。 我們將其作為 URL 編碼格式傳遞。 目前,該應用程序以 JSON 格式逐字返回字符串——第一個字段始終返回字符串markdown
,第二個字段返迴轉換後的文本。 稍後,當我們添加 Markdown 處理代碼時,它會返迴轉換後的文本。
第三階段:添加 Markdown 轉換器
現在構建了應用程序腳手架,我們可以查看Showdown
JavaScript 庫,我們將使用它來將 Markdown 轉換為 HTML。 Showdown 是一個用 JavaScript 編寫的雙向 Markdown 到 HTML 轉換器,它允許您將 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)
。 我們可以使用setOption
方法為 Markdown 轉換設置各種選項,格式如下:
converter.setOption('optionKey', 'value');
因此,例如,我們可以設置一個選項來自動插入和鏈接指定的 URL,而無需任何標記。
converter.setOption('simplifiedAutoLink', 'true');
與 Postman 示例一樣,如果我們向應用程序傳遞一個簡單的字符串(例如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-to-HTML 轉換器。 讓我們進一步並添加身份驗證以具有應用程序。
第 4 階段:使用 Passport 添加 API 身份驗證
在沒有適當身份驗證的情況下向外界公開您的應用程序 API 將鼓勵用戶無限制地查詢您的 API 端點。 這將邀請不道德的元素濫用您的 API,並且還會給您的服務器帶來未經審核的請求。 為了緩解這種情況,我們必須添加適當的身份驗證機制。
我們將使用 Passport 包向我們的應用程序添加身份驗證。 就像我們之前遇到的body-parser
中間件一樣,Passport 是 Node.js 的身份驗證中間件。 我們將使用 Passport 的原因是它有多種身份驗證機制可供使用(用戶名和密碼、Facebook、Twitter 等),這使用戶可以靈活地選擇特定機制。 Passport 中間件可以輕鬆地放入任何 Express 應用程序中,而無需更改太多代碼。
使用 npm 安裝包。
$ npm install passport
我們還將使用local
策略(稍後將解釋)進行身份驗證。 所以也安裝它。
$ npm install passport-local
您還需要為 Passport 使用的 Node.js 添加 JWT(JSON Web Token) 編碼和解碼模塊:
$ 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 會話如下所示。
在這裡,我們可以看到我們已經從 Markdown 語法中獲得了正確的 HTML 轉換字符串。 雖然我們只要求轉換一行 Markdown,但是 API 可以轉換大量的文本。
這結束了我們使用 Node.js 和 Express 構建 API 端點的簡短嘗試。 API 構建是一個複雜的主題,在構建 API 時應該注意一些更細微的細微差別,遺憾的是我們沒有時間在這裡討論,但可能會在以後的文章中介紹。
從另一個應用程序訪問我們的 API
現在我們已經構建了一個 API,我們可以創建一個小的 Node.js 腳本來向您展示如何訪問該 API。 對於我們的示例,我們需要安裝request
npm 包,它提供了一種簡單的方式來發出 HTTP 請求。 (您很可能已經安裝了這個。)
$ npm install request --save
下面給出了向我們的 API 發送請求並獲取響應的示例代碼。 如您所見, request
包大大簡化了問題。 要轉換的降價在textToConvert
變量中。
在運行以下腳本之前,請確保我們之前創建的 API 應用程序已經在運行。 在另一個命令窗口中運行以下腳本。
注意:我們使用(back-tick)
符號來跨越textToConvert
變量的多個 JavaScript 行。 這不是單引號。
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)); });
當我們向 API 發出 POST 請求時,我們會提供要轉換的 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 進行了硬編碼,但文本可以來自各種其他來源——文件、Web 表單等。 請求過程保持不變。
請注意,由於我們將請求作為application/json
內容類型發送; 我們需要使用 json 對主體進行編碼,因此需要調用JSON.stringify
函數。 如您所見,測試或 API 應用程序需要一個非常小的示例。
結論
在本文中,我們開始了一個教程,目的是學習如何使用 Node、js 和 Express 框架來構建 API 端點。 我們決定創建一個將 Markdown 語法轉換為 HTML 的 API,而不是毫無目的地構建一些虛擬應用程序,從而在有用的上下文中錨定或學習。 在此過程中,我們向 API 端點添加了身份驗證,並且我們還看到了使用 Postman 測試應用程序端點的方法。