自定義類似express.urlencoded解析 POST 提交到伺服器的表單資料
阿新 • • 發佈:2020-10-21
自定義中介軟體
1 需求描述與實現步驟
1.1 需求以及實現步驟
-
需求描述: 自己手動模擬一個類似於
express.urlencoded
這樣的中介軟體,來解析 -
實現步驟:
-
定義中介軟體
-
監聽
req
的data
事件 -
監聽
req
的end
事件 -
使用
querystring
模組解析請求體資料 -
將解析出來的資料物件掛載為
req.body
-
將自定義中介軟體封裝為模組
-
1.2 定義中介軟體
-
使用
app.use()
來定義全域性生效的中介軟體 -
程式碼如下:
-
// 匯入 express 模組 const express = require('
監聽 req
的 data
事件
-
在中介軟體中,需要監聽
req
物件的data
事件,來獲取客戶端傳送到伺服器的資料 -
如果資料量比較大,無法一次性發送完畢,則客戶端會把資料切割後,分批發送到伺服器。所以
data
data
事件時,獲取到資料只是完整資料的一部分,需要手動對接收到的資料進行拼接 -
程式碼如下:
-
// 匯入 express 模組 const express = require('express') // 建立 express 的伺服器例項 const app = express() // 解析表單資料的中介軟體 app.use((req, res, next) => { // 定義中間價具體的業務邏輯 // 1. 定義一個 str 字串,專門用來儲存客戶端傳送過來的請求體資料 let str = '' // 2. 監聽 req 的 data 事件 req.on('
監聽 req
的 end
事件
-
當請求體資料接收完畢之後,會自動觸發
req
的end
事件 -
我們可以在
req
的end
事件中,拿到並處理完整的請求體資料 -
程式碼如下
// 匯入 express 模組 const express = require('express') // 建立 express 的伺服器例項 const app = express() // 解析表單資料的中介軟體 app.use((req, res, next) => { // 定義中間價具體的業務邏輯 // 1. 定義一個 str 字串,專門用來儲存客戶端傳送過來的請求體資料 let str = '' // 2. 監聽 req 的 data 事件 req.on('data', (chunk) => { str += chunk }) // 3. 監聽 req 的 end 事件 req.on('end', () => { // 在 str 中存放的是完整的請求體資料 console.log(str) // 將字串格式的請求體資料,解析成物件 }) }) app.post('/user', (req, res) => { res.send('ok') }) // 呼叫 app.listen方法,指定埠號並啟動 web 伺服器 app.listen(3000, () => { console.log('running……') })
用 querystring
模組解析請求體資料
-
Node.js
內建了一個querystring
模組,專門用來處理查詢字串。通過這個模組提供的parse()
函式,可以輕鬆把查詢字串,解析成物件的格式 -
程式碼如下
// 匯入 express 模組 const express = require('express') // 建立 express 的伺服器例項 const app = express() // 4. 匯入 Node 內建模組 querystring const qs = require('querystring') // 解析表單資料的中介軟體 app.use((req, res, next) => { // 定義中間價具體的業務邏輯 // 1. 定義一個 str 字串,專門用來儲存客戶端傳送過來的請求體資料 let str = '' // 2. 監聽 req 的 data 事件 req.on('data', (chunk) => { str += chunk }) // 3. 監聽 req 的 end 事件 req.on('end', () => { // 在 str 中存放的是完整的請求體資料 console.log(str) // 將字串格式的請求體資料,解析成物件 // 5. 呼叫 qs.parse() 方法,將查詢字串解析成物件 const body = qs.parse(str) console.log(body) }) }) app.post('/user', (req, res) => { res.send('ok') }) // 呼叫 app.listen方法,指定埠號並啟動 web 伺服器 app.listen(3000, () => { console.log('running……') })
將解析出來的資料物件掛載為 req.body 1. 上游的中介軟體和下游的中介軟體及路由之間,共享同一份 req 和 res,因此,我們可以將解析出來的資料,掛載為 req 的自定義屬性,命名為 req.body,供下游使用 2. 程式碼如下
// 匯入 express 模組 const express = require('express') // 建立 express 的伺服器例項 const app = express() // 4. 匯入 Node 內建模組 querystring const qs = require('querystring') // 解析表單資料的中介軟體 app.use((req, res, next) => { // 定義中間價具體的業務邏輯 // 1. 定義一個 str 字串,專門用來儲存客戶端傳送過來的請求體資料 let str = '' // 2. 監聽 req 的 data 事件 req.on('data', (chunk) => { str += chunk }) // 3. 監聽 req 的 end 事件 req.on('end', () => { // 在 str 中存放的是完整的請求體資料 console.log(str) // 將字串格式的請求體資料,解析成物件 // 5. 呼叫 qs.parse() 方法,將查詢字串解析成物件 const body = qs.parse(str) // 6. 將解析出來的資料物件掛載為 req.body 屬性 req.body = body next() }) }) app.post('/user', (req, res) => { res.send(req.body) }) // 呼叫 app.listen方法,指定埠號並啟動 web 伺服器 app.listen(3000, () => { console.log('running……') })
將自定義中介軟體封裝為模組
-
為了優化程式碼的結構,我們可以把自定義的中介軟體函式,封裝為獨立的模組
-
程式碼如下:
// custom-body-parser.js const qs = require('querystring') const bodyParser = (req, res, next) => { // 定義中間價具體的業務邏輯 // 1. 定義一個 str 字串,專門用來儲存客戶端傳送過來的請求體資料 let str = '' // 2. 監聽 req 的 data 事件 req.on('data', (chunk) => { str += chunk }) // 3. 監聽 req 的 end 事件 req.on('end', () => { // 在 str 中存放的是完整的請求體資料 console.log(str) // 將字串格式的請求體資料,解析成物件 // 5. 呼叫 qs.parse() 方法,將查詢字串解析成物件 const body = qs.parse(str) // 6. 將解析出來的資料物件掛載為 req.body 屬性 req.body = body next() }) } module.exports = bodyParser
// 對自定義的中介軟體進行模組化拆分 // 匯入 express 模組 const express = require('express') // 建立 express 的伺服器例項 const app = express() // 1. 匯入自己封裝的中介軟體模組 const customBodyParser = require('./017-custom-body-parser') // 2. 將自定義的中介軟體函式,註冊為全域性可用的中介軟體 app.use(customBodyParser) app.post('/user', (req, res) => { res.send(req.body) }) // 呼叫 app.listen方法,指定埠號並啟動 web 伺服器 app.listen(3000, () => { console.log('running……') })