实现 ~ body-parser

670 阅读1分钟
  • body-parser
  • 作用: 解析请求体
  • 服务端框架 express

用法

client.js

let http = require('http');

let client = http.request({
    hostname:'localhost',
    port:3000,
    path:'/',
    method:'post',
    headers:{
        'Content-Type':'application/x-www-form-urlencode'
    }
},function (res) {
});
client.end('name=zdl&age=9');

express.js


//
const express = require('express');
const app = express();
const bodyParser = require('body-parser');

// 中间件用法
app.use(bodyParser.urlencoded({extended:true}))
app.post('/',function(req,res){
    console.log(req.body);
    res.end();
})
app.listen(3000)

解析后运行express.js node client.js,输出{ name: 'zdl', age: '9' }

实现

urlencoded 之'Content-Type':'application/x-www-form-urlencode'

function urlencoded({extended}){
    return (req,res,next)=>{
        let buffers = [];
        req.on('data',function(data){
            buffers.push(data);
        })
        req.on('end',function(){
            let str = Buffer.concat(buffers).toString();
            if(extended){
                req.body = require('querystring').parse(str);
            }else{
                req.body = require('qs').parse(str); 
            }
            next()
        })
    }
}
app.use(urlencoded({extended:true}))

注: querystring不支持嵌套,故而有extended的区分

urlencoded 之 'Content-Type':'text/plain;charset=gbk'

text很简单,但是有点小麻烦,因为假设用户传的是gbk格式,而 node又不支持这种格式,我们需要用到iconv-lite库转码(需要安装),

  • 首先我们需要将'Content-Type'格式转换成'text/plain;charset=gbk'
  • 引用iconv-lite 传输数据
  • 安装content-type包解析编码格式
let http = require('http');

let client = http.request({
    hostname:'localhost',
    port:3000,
    path:'/',
    method:'post',
    headers:{
 'Content-Type':'text/plain;charset=gbk'
 }
},function (res) {
});
let iconv = require('iconv-lite');
client.end(iconv.encode('我很帅','gbk'));

express.js

function text(){
    return (req,res,next)=>{
        let buffers = [];
        req.on('data',function(data){
            buffers.push(data);
        })
        req.on('end',function(){
            let str = Buffer.concat(buffers);
            let contentType = require('content-type');
            let iconvLite = require('iconv-lite');
            let { parameters: { charset }, type} = contentType.parse(req.headers['content-type']);
            if(type === 'text/plain'){
                // 解码操作
                req.body = iconvLite.decode(str, charset);
                console.log(req.body);
            }
            next()
        })
    }
}
app.use(text())

所以完整express.js如下

let express = require('express');
let app = express();
let bodyParser = require('body-parser');
function urlencoded({extended}){
    return (req,res,next)=>{
        let buffers = [];
        req.on('data',function(data){
            buffers.push(data);
        })
        req.on('end',function(){
            let str = Buffer.concat(buffers).toString();
            if(extended){
                req.body = require('querystring').parse(str);
            }else{
                req.body = require('qs').parse(str); 
            }
            next()
        })
    }
}
app.use(urlencoded({extended:true}))
function text(){
    return (req,res,next)=>{
        let buffers = [];
        req.on('data',function(data){
            buffers.push(data);
        })
        req.on('end',function(){
            let str = Buffer.concat(buffers);
            let contentType = require('content-type');
            let iconvLite = require('iconv-lite');
            let { parameters: { charset }, type} = contentType.parse(req.headers['content-type']);
            if(type === 'text/plain'){
                // 解码操作
                req.body = iconvLite.decode(str, charset);
                console.log(req.body);
            }
            next()
        })
    }
}
app.use(text())
app.post('/',function(req,res){
    console.log(req.body);
    res.end();
})
app.listen(3000)