1. 程式人生 > 實用技巧 >自定義類似express.urlencoded解析 POST 提交到伺服器的表單資料

自定義類似express.urlencoded解析 POST 提交到伺服器的表單資料

自定義中介軟體

1 需求描述與實現步驟

1.1 需求以及實現步驟
  1. 需求描述: 自己手動模擬一個類似於 express.urlencoded 這樣的中介軟體,來解析 POST 提交到伺服器的表單資料

  2. 實現步驟:

    • 定義中介軟體

    • 監聽 reqdata 事件

    • 監聽 reqend 事件

    • 使用 querystring 模組解析請求體資料

    • 將解析出來的資料物件掛載為 req.body

    • 將自定義中介軟體封裝為模組

1.2 定義中介軟體
  1. 使用 app.use() 來定義全域性生效的中介軟體

  2. 程式碼如下:

  3. // 匯入 express 模組
    const express = require('
    express') // 建立 express 的伺服器例項 const app = express() // 解析表單資料的中介軟體 app.use((req, res, next) => { // 定義中間價具體的業務邏輯 }) // 呼叫 app.listen方法,指定埠號並啟動 web 伺服器 app.listen(3000, () => { console.log('running……') })

監聽 reqdata 事件

  1. 在中介軟體中,需要監聽 req 物件的 data 事件,來獲取客戶端傳送到伺服器的資料

  2. 如果資料量比較大,無法一次性發送完畢,則客戶端會把資料切割後,分批發送到伺服器。所以 data

    事件可能會觸發多次,每一次觸發 data 事件時,獲取到資料只是完整資料的一部分,需要手動對接收到的資料進行拼接

  3. 程式碼如下:

  4. // 匯入 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 }) }) // 呼叫 app.listen方法,指定埠號並啟動 web 伺服器 app.listen(3000, () => { console.log('running……') })

監聽 reqend 事件

  1. 當請求體資料接收完畢之後,會自動觸發 reqend 事件

  2. 我們可以在 reqend 事件中,拿到並處理完整的請求體資料

  3. 程式碼如下

// 匯入 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 模組解析請求體資料

  1. Node.js 內建了一個 querystring 模組,專門用來處理查詢字串。通過這個模組提供的 parse() 函式,可以輕鬆把查詢字串,解析成物件的格式

  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)
    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……')
})

將自定義中介軟體封裝為模組

  1. 為了優化程式碼的結構,我們可以把自定義的中介軟體函式,封裝為獨立的模組

  2. 程式碼如下:

// 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……')
})