Nodejs的Express框架本身所提供的東西並沒有其它框架那麼多。其中的一個問題就是對於請求數據的解析。
express中的請求對象並沒有未經過解析的請求體,幾乎所有的請求體都要經過類似於body-parser這類包來實現對其解析。
例如,像請求體是json格式的數據,而Content-Type: application/json時,body-parser會將請求體作爲json字符串解析成爲一個對象,並賦值給req.body。代碼如下:
const bodyParser = require('body-parser');
app.route('/path').post(bodyParser.json(), function(req, res){res.end('1')});
但此處有個問題,就是當客戶端發起的請求中請求體不合法的時候,應用程序將會500內部錯誤。其原因在於bodyParser.json()認爲請求體是合法的json字符串,而沒有考慮到錯誤的情況。
我們希望在客戶端請求內容無效的時候可以返回相應的提示信息而不是內部錯誤,一種不太完美的方法是使用bodyParser.json()的verify參數:
const bodyParser = require('body-parser');
const jsonParse = bodyParser.json({
verify: function(req, res, buf, encoding){
try{
res.body = buf.toString();
}catch(err){
return res.json({code:'1',status:"Invalid Parameters"})
}
}
})
app.route('/path').post(jsonParse, function(req, res){res.end('1')});
這種方法在參數不合法的時候返回預期的響應,不至於將服務器的錯誤暴露出來。這種在應用程序內部還是會觸發異常,這個異常出現在res.json()中,程序會提示響應頭在設置了之後不能再改動。也就是在bodyParser.json()這個響應體的內部產生了兩次對res響應體的操作,一次是verify,一次是將內容向json轉化的時候。
另一種解決方法是不使用bodyParser.json(),而使用body.raw(),配合自定義的json解析函數進行實現前述的功能:
const bodyParser = require('body-parser');
const rawParse = bodyParser.raw({
type: "*/*",
verify: function(req, res, buf, encoding){
res.raw = buf.toString();
})
})
const jsonParse = function(req, res, next){
try{
req.body = JSON.parse(req.raw);
}catch(err){
return res.json({code:"-1", status:"Invalid Parameters"})
}
}
app.route('/path').post(rawParse, jsonParse, function(req, res){res.end('1')});
這樣就可以解決前述請求體類型錯誤所導致錯誤。當然這種方法目前只能用於接口數量比較少的情況,在接口數量十分多的情況下,相較於app.use(bodyParser.json()),就顯得十分笨拙了。
但由於使用了app.use之後,所有的接口都會首先經過這麼一步解析,也無法對個別請求的參數檢驗進行個性化定製。
目前暫時只能想到這種解決辦法,有後續的方法會持續更新。