bodyParser中間件的研究

wtpn3621 9年前發布 | 9K 次閱讀 中間件 Node.js 開發

來自: http://www.cnblogs.com/lianer/p/5178693.html

bodyParser中間件的研究

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

// 瀏覽器端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' } });</pre>

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

bodyParser中間件

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

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

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

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

常見的四種Content-Type類型:

  • application/x-www-form-urlencoded 常見的form提交
  • multipart/form-data 文件提交
  • application/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' ] }</pre>

可以看出,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' ] } });</pre>

參考資料

大多時候,我們只知道如何去使用,而不知道為什么這么用。

</div>

 本文由用戶 wtpn3621 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!