- 原文地址:Building A Node.js Express API To Convert Markdown To HTML
- 原文做者:Sameer Borate
- 譯文出自:掘金翻譯計劃
- 本文永久連接:github.com/xitu/gold-m…
- 譯者:Baddyo
- 校對者:fireairforce, JackEggie
快速摘要:搭建一個把 Markdown 語法轉換爲 HTML 的應用,經過該實踐來學習如何使用 Node.js 和 Express 框架建立接口端點。javascript
Markdown 是一種輕量級的文本標記語言,能將帶標記的文本轉換爲各類格式。發明 Markdown 的初衷,是爲了讓人們能「用易讀易寫的純文本格式來書寫」,並能夠按需轉換爲有效的 XHTML(或者 HTML)。目前,隨着 WordPress 的支持,Markdown 語法愈來愈流行了。html
本文旨在向讀者展現如何用 Node.js 和 Express 框架建立接口端點。咱們會搭建一個將 Markdown 轉換爲 HTML 的應用,在搭建過程當中學習 Node.js 和 Express。咱們還會給接口添加驗證機制,以防咱們的應用被濫用。前端
咱們把這個小巧玲瓏的應用叫作 「Markdown 轉換器」,咱們把 Markdown 語法的文本上傳給它,而後獲得 HTML 格式的版本。該應用使用 Node.js 的框架 Express 實現,並支持對轉換請求的驗證。java
咱們會化整爲零地實現這個應用 —— 先用 Express 建立一個基本框架,而後再添加驗證機制等功能。那就讓咱們開始搭建基本框架吧!node
假設你已經在操做系統裏安裝了 Node.js,如今咱們建立一個文件夾(就叫它 「markdown-api
」 吧)來存放代碼,並進入該文件夾:android
$ mkdir markdown-api
$ cd markdown-api
複製代碼
使用 npm init 命令建立一個 package.json 文件。該命令會提示你輸入諸如應用名稱、版本之類的信息。ios
就本次實踐來講,你只需按下 Enter 鍵使用那些默認信息就好。我把 index.js 作爲默認入口文件,但你也能夠按本身喜愛設置成 app.js 或別的文件。git
如今咱們在 markdown-api
目錄下安裝 Express,並將其列入依賴包列表:github
$ npm install express --save
複製代碼
在當前目錄(markdown-api
)建立一個 index.js 文件,把下列代碼添加進去來測試 Express 框架是否安裝成功:web
const express = require('express');
var app = express();
app.get('/', function(req, res){
res.send('Hello World!');
});
app.listen(3000);
複製代碼
訪問 http://localhost:3000
,看看測試文件是否成功運行起來了。若是一切順利,咱們能在瀏覽器中看到 「Hello World!」 字樣,那接下來就能夠構建 Markdown 轉 HTML 的基本接口了。
該接口的主要做用是把 Markdown 轉爲 HTML,它將有兩個端點:
/login
/convert
login
端點用來驗證有效請求;convert
端點用來進行 Markdown 到 HTML 的轉換。
如下是調用兩個端點的基本接口代碼。調用 login
會返回一個 「Authenticated」 字符串,而調用 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
屬性中供你使用。雖然說不借助中間件也能解析請求,但那樣就太麻煩了。
用 npm 就能夠安裝 body-parser
:
$ npm install body-parser
複製代碼
如今萬事俱備,咱們得用 Postman 測試一下。先簡單介紹一下 Postman 吧。
Postman 是一種接口開發工具,使用其網頁版或者桌面客戶端(網頁版下架了)能夠極爲方便地搭建、修改以及測試接口端點。它能夠生成各類類型的 HTTP 請求,例如 GET、POST、PUT 和 PATCH。Postman 支持 Windows、macOS 和 Linux。
來一睹 Postman 的風采吧:
(高清大圖)
要想調用一個接口端點,你須要遵循如下步驟:
Postman 會把請求發送給應用,取得響應信息並顯示在界面下方的窗口中。這就是 Postman 的基本用法。在咱們的應用中,咱們還要給請求添加其餘參數,這一塊內容後面會說到。
大概熟悉了 Postman 以後,咱們就要實際使用它了。
用命令行啓動 markdown-api
應用:
$ node index.js
複製代碼
爲了測試基本接口代碼,咱們要用 Postman 調用接口。注意,咱們用 POST 方法把要轉換的文本傳給應用。
咱們的應用經過 POST 方法的 content
參數接收待轉換的文本。咱們把它做爲 URL 編碼格式傳遞。字符串以 JSON 的格式返回 —— 第一個字段總會返回字符串 markdown
,而第二個字段返回轉換後的文本。而後,當咱們添加了 Markdown 處理代碼,它就會返回轉換後的文本。
應用的基本框架搭建好了,咱們就來看看 showdown
這個 JavaScript 庫,咱們要用此庫把 Markdown 轉換爲 HTML。showdown
是用 JavaScript語言實現的,支持 Markdown 和 HTML 之間的雙向轉換。
(高清大圖)
用 npm 安裝 showdown
:
$ npm install showdown
複製代碼
添加所需的 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
方法能夠對轉換過程進行各類配置:
converter.setOption('optionKey', 'value');
複製代碼
例如,能夠配置成自動插入特定的 URL 而不用任何標記。
converter.setOption('simplifiedAutoLink', 'true');
複製代碼
在 Postman 的例子中,若是咱們把 simplifiedAutoLink
的值配置爲 true
,傳一個簡單的字符串(例如 Google home http://www.google.com/
)時就會返回以下結果:
<p>Google home <a href="http://www.google.com/">http://www.google.com/</a></p>
複製代碼
不然,要實現相同效果,咱們必需要添加標記信息才行:
Google home <http://www.google.com/>
複製代碼
還有不少配置項能夠控制 Markdown 的轉換過程。你能夠在這裏找到完整的配置項列表。
如今,咱們實現了一個能將 Markdown 轉爲 HTML 的「轉換器」端點。讓咱們繼續深刻來添加驗證功能吧。
不給接口添加恰當的驗證機制就把它扔出去給別人使用,就是在鼓勵使用者無限制地使用你的接口。這會招致某些無恥之徒濫用接口,蜂擁而至的請求會拖垮你的服務器。爲了不這樣的局面,咱們必須給接口添加恰當的驗證機制。
咱們將用 Passport 包來實現驗證機制。正如以前用到的 body-parser
中間件同樣,Passport 是一個基於 Node.js 的驗證中間件。使用它的緣由在於,它支持各類驗證機制(用戶名和密碼驗證、Facebook 帳號驗證、Twitter 帳號驗證等等),這樣咱們能夠靈活選擇驗證方式。添加 Passport 中間件很簡單,無需更改過多代碼。
用 npm 安裝 Passport:
$ npm install passport
複製代碼
咱們還要使用 local
策略來進行驗證,稍後我會詳細說明。所以要把 passport-local
也安裝上。
$ npm install passport-local
複製代碼
你還須要編碼/解碼模塊 JWT(JSON Web Token):
$ npm install jwt-simple
複製代碼
Passport 中間件使用策略的概念來驗證請求。這裏所謂的策略就是一系列方法,它們幫你驗證各類請求,從簡單的用戶名密碼驗證,到開放受權驗證(Facebook 或 Twitter 帳號驗證),再到 OpenID 驗證,皆可勝任。一個應用所使用的驗證策略須要預先配置才能去驗證請求。
在咱們本身的應用中,咱們會用個簡單的用戶名密碼驗證方案,這樣便於理解和編碼。目前,Passport 支持超過 300 種驗證策略。
雖然 Passport 的設計很複雜,但實際使用卻很簡單。下面的例子就展現了 /convert
端點如何添加驗證機制。如你所見,垂手可得。
app.post("/convert",
passport.authenticate('local',{ session: false, failWithError: true }),
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]);
}},
// 驗證失敗,返回 「Unauthorized」 字樣
function(err, req, res, next) {
return res.status(401).send({ success: false, message: err })
});
複製代碼
如今,除了要轉換的 Markdown 字符串,咱們還要發送用戶名和密碼,與應用的用戶名密碼比對驗證。由於咱們使用的是本地驗證策略,驗證憑證就會存儲在代碼自己中。
可能這樣的驗證手段看起來太簡陋了,但對於一個 demo 級別的應用來講已經足夠。簡單的例子也有助於咱們理解驗證過程。順便說一句,有種常見的安全措施是把憑證存到環境變量中。固然,不少人對這種方式不覺得然,但我以爲這是個相對安全的方法。
驗證功能的完整示例以下:
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) {
// 若此函數被調用,說明驗證成功。
// 返回 「Authenticated」 字樣。
res.send("Authenticated");
});
app.post("/convert",
passport.authenticate('local',{ session: false, failWithError: true }),
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]);
}},
// 驗證失敗,返回 「Unauthorized」 字樣
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 測試最終應用(高清大圖)
在此可見,咱們上傳了一段 Markdown 語法的文本,而後獲得了通過正確轉換的 HTML 版本的結果。咱們只是測試了一行文本,但這個接口是有轉換大段文本的能力的。
這就是咱們這次對 Node.js 和 Express 的淺嘗 —— 搭建一個接口端點。構建接口是一個複雜的課題,在你想構建一個接口的時候,有些細節你應該清楚,但時間有限,很抱歉不能在本文中展開了,但可能會在後續文章中詳細探討。
既然已經搭建好了接口,那咱們就能夠寫一個基於 Node.js 的小腳原本證實接口可用。在本例中,咱們須要安裝 request
包以便於發送 HTTP 請求。(極可能你已經安裝過了)
$ npm install request --save
複製代碼
下面所示代碼向咱們的接口發送了一個請求,並獲得了響應。如你所見,request
包大大簡化了步驟。待轉換的 Markdown 文本存放於 textToConvert
變量中。
在運行下列腳本以前,你要確保接口應用已經處於運行狀態。你須要在另外的命令窗口中運行腳本。
注意:在變量 textToConvert
中,咱們使用了 「 ` 」 符號來包裹多行 JavaScript 代碼,它不是單引號哦。
var Request = require("request");
// 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](http://example.com). Horizontal rule:`;
// Markdown 文本的結尾
Request.post({
"headers": { "content-type": "application/json" },
"url": "http://localhost:3000/convert",
"body": JSON.stringify({
"content": textToConvert,
"username": "admin",
"password": "smagazine"
})
}, function(error, response, body){
// 鏈接失敗時,退出。
if(error) {
return console.log(error);
}
// 顯示轉換後的文本
console.dir(JSON.parse(body));
});
複製代碼
當發送 POST 請求到接口時,咱們須要提供要轉換的 Markdown 文本和身份憑證。若是憑證錯誤,咱們會收到錯誤提示信息。
{
success: false,
message: {
name: 'AuthenticationError',
message: 'Unauthorized',
status: 401
}
}
複製代碼
對於一個驗證經過的請求,上述 Markdown 樣例會被轉換爲以下格式:
[ 'markdown',
`<h1 id="heading">Heading</h1>
<h2 id="subheading">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="http://example.com">link</a>.
Horizontal rule:</p>` ]
複製代碼
在例子中咱們刻意寫了一段 Markdown 文本,實際狀況中的文本可能來自文件、web 表單等多種來源。但請求過程都是同樣的。
注意:當咱們使用 application/json
格式發送請求時,咱們須要用 JSON 格式解析響應體,故而要調用 JSON.stringify
函數。如你所見,測試或者接口應用僅需一個小例子,在此不贅述。
在本文中,咱們以學習使用 Node.js 和 Express 框架搭建接口爲目的組織了一次教程。與其漫無目的地作一些沒意思的應用,不如搭建一個把 Markdown 轉換爲 HTML 的接口,這纔算是有用的實踐。經過整個過程的實踐,咱們學會了給接口端點添加驗證機制,還學會了用 Postman 測試應用的幾種方式。
若是發現譯文存在錯誤或其餘須要改進的地方,歡迎到 掘金翻譯計劃 對譯文進行修改並 PR,也可得到相應獎勵積分。文章開頭的 本文永久連接 即爲本文在 GitHub 上的 MarkDown 連接。
掘金翻譯計劃 是一個翻譯優質互聯網技術文章的社區,文章來源爲 掘金 上的英文分享文章。內容覆蓋 Android、iOS、前端、後端、區塊鏈、產品、設計、人工智能等領域,想要查看更多優質譯文請持續關注 掘金翻譯計劃、官方微博、知乎專欄。