bodyParser中間件的研究

bodyParser中間件的研究

接觸nodejs已有一段時間了,但最近纔開始落實項目,因而使用express應用生成器生成了一個應用。開發過程當中發現ajax提交的數據沒法被express正確的解析,主要的狀況是這樣的:javascript

// 瀏覽器端post一個對象
$.ajax({
    url: "/save",
    type: "post",
    data: {
        name: "henry",
        age: 30,
        hobby: [ "sport", "coding" ]
    }
});

// express接收這個對象
router.post("/save", function (req, res, next) {
    console.log(req.body); // => { 'info[name]': 'henry','info[age]': '30','hobby[1]': 'sport','hobby[2]': 'coding' }
});

顯然這樣的解析結果是不能直接拿來用的,莫名其妙的一個坑,困了我許久。java

bodyParser中間件

bodyParser中間件用來解析http請求體,是express默認使用的中間件之一。node

使用express應用生成器生成一個網站,它默認已經使用了 bodyParser.jsonbodyParser.urlencoded 的解析功能,除了這兩個,bodyParser還支持對text、raw的解析。jquery

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));

顧名思義,bodyParser.json是用來解析json數據格式的。bodyParser.urlencoded則是用來解析咱們一般的form表單提交的數據,也就是請求頭中包含這樣的信息: Content-Type: application/x-www-form-urlencodedgit

常見的四種Content-Type類型:github

  • application/x-www-form-urlencoded 常見的form提交ajax

  • multipart/form-data 文件提交express

  • application/json 提交json格式的數據json

  • text/xml 提交xml格式的數據數組

詳細解讀 urlencoded

bodyParser.urlencoded 模塊用於解析req.body的數據,解析成功後覆蓋原來的req.body,若是解析失敗則爲 {}。該模塊有一個屬性extended,官方介紹以下:

The extended option allows to choose between parsing the URL-encoded data with the querystring library (when false) or the qs library (when true). Defaults to true, but using the default has been deprecated.

大體的意思就是:extended選項容許配置使用querystring(false)或qs(true)來解析數據,默認值是true,但這已是不被同意的了。

querystring就是nodejs內建的對象之一,用來字符串化對象或解析字符串。如

querystring.parse("name=henry&age=30") => { name: 'henry', age: '30' }

那麼,既然querystring已經能完成對urlencode的解析了,爲何還須要qs?qs又是什麼?

qs介紹

qs是一個querystring的庫,在qs的功能基礎上,還支持更多的功能並優化了一些安全性。好比,對象解析的支持:

// 內建對象 querystring
querystring.parse("info[name]=henry&info[age]=30&hobby[1]=sport&hobby[2]=coding") => 
  { 
    'info[name]': 'henry',
    'info[age]': '30',
    'hobby[1]': 'sport',
    'hobby[2]': 'coding'
  }

// 第三方插件 qs
qs.parse("info[name]=henry&info[age]=30&hobby[1]=sport&hobby[2]=coding") => 
  {
    info: {
      name: 'henry',
      age: '30'
    },
    hobby: [ 'sport', 'coding' ]
  }

能夠看出,querystring並不能正確的解析複雜對象(多級嵌套),而qs卻能夠作到。

可是qs也不是萬能的,對於多級嵌套的對象,qs只會解析5層嵌套,超出的部分會表現的跟本文頭部的那種狀況同樣;對於數組,qs最大隻會解析20個索引,超出的部分將會以鍵值對的形式解析。

做爲一箇中間件,qs必需要爲性能考慮,纔會有如此多的限制,express也默認使用qs來解析請求體。

理論上來講,form表單提交不會有多級嵌套的狀況,而urlencoded自己也是form的內容類型,所以,bodyParser.urlencoded不支持多級嵌套也是很合理的設計。

那麼,若是咱們非要上傳一個十分複雜的對象,應該怎麼辦?

解決方案

出現這個問題的根本緣由是:我以form的形式去提交了一個json數據。

jquery默認的 content-Type 配置的是 application/x-www-form-urlencoded

所以更改ajax請求參數:contentType: "application/json",並將數據轉成json提交,問題就解決了。

// 瀏覽器端post一個對象
$.ajax({
    url: "/save",
    type: "post",
    contentType: "application/json",
    data: JSON.stringify({
        name: "henry",
        age: 30,
        hobby: [ "sport", "coding" ]
    })
});

// express接收這個對象
router.post("/save", function (req, res, next) {
    console.log(req.body); // => { name: 'henry', age: 30, hobby: [ 'sport', 'coding' ] }
});

參考資料

大多時候,咱們只知道如何去使用,而不知道爲何這麼用。

相關文章
相關標籤/搜索