文章目录
自定义中间件
1 需求描述与实现步骤
自己手动模拟一个类似于express.urlencoded
这样的中间件,来解析POST提交到服务器的表单数据。
- 定义中间件
- 监听req的data事件
- 监听req的end事件
- 使用querystring模块解析请求体数据
- 将解析出来的数据对象挂载为req.body
- 将自定义中间件封装为模块
2 定义中间件
使用app.use()
来定义全局生效的中间件,代码如下:
app.use((req, res, next) => {// 中间件的业务逻辑next()
})
3 监听req的data事件
在中间件中,需要监听req对象的data事件,来获取客户端发送到服务器的数据。
如果数据量比较大,无法一次性发送完毕,则客户端会把数据切割后,分批发送到服务器。所以dta事件可能会触发多次,每一次触发dta事件时,获取到数据只是完整数据的一部分,需要手动对接收到的数据进行拼接。
// 1. 定义一个 str 字符串,专门用来存储客户端发送过来的请求体数据
let str = ''// 2. 监听 req 的data事件
req.on('data', (chunk) => {str += chunk
})
4 监听req的end事件
当请求体数据接收完毕之后,会自动触发req的end事件。
因此,我们可以在req的end事件中,拿到并处理完整的请求体数据。示例代码如下:
// 3. 监听 req 对象的 end 事件
req.on('end', () => {// 在str中存放的就是完整的请求体数据console.log(str)
})
5 使用querystring模块解析请求体数据
Node.js内置了一个querystring模块,专门用来处理查询字符串。通过这个模块提供的parse()
函数,可以轻松把查询字符串,解析成对象的格式。示例代码如下:
const qs = require('querystring')const body = qs.parse(str)
6 将解析出来的数据对象挂载为req.body
上游的中间件和下游的中间件及路由之间,共享同一份req和res。因此,我们可以将解析出来的数据,挂载为req的自定义属性,命茗为req.body, 供下游使用。示例代码如下:
// 3. 监听 req 对象的 end 事件
req.on('end', () => {// 在str中存放的就是完整的请求体数据const body = qs.parse(str)req.body = bodyconsole.log("中间件", req.body)next()
})
7 自定义中间件
为了优化代码的结构,我们可以把自定义的中间件函数,封装为独立的模块,示例代码如下:
//custom-body-parser.js 模块中的代码
const qs = require('querystring')
function bodyParser(req,res,next){/*省略其它代码*/}
module.exports = bodyParser//向外导出解析请求体数据的中间件函数// ------------------分隔线----------------------
//1,导入自定义的中间件模块
const myBodyParser = require('custom-body-parser')
//2,注册自定义的中间件模块
app.use(myBodyParser)
8 最终代码
index.js
// 导入express
const express = require('express')
const bodyParser = require('./custom-body-parser')// 创建web服务器
const app = express()// 解析表单数据的中间件
app.use(bodyParser)app.post('/user', (req, res) => {console.log("路由接口:", req.body)res.send(req.body)
})// 启动服务器
app.listen(80, () => {console.log('express server running at http://127.0.0.1')
})
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中存放的就是完整的请求体数据req.body = qs.parse(str)console.log("中间件", req.body)next()})
}module.exports = bodyParser