簡體   English   中英

NodeJS RESTful API-如何正確處理“未定義”的請求變量?

[英]NodeJS RESTful API - How to handle 'undefined' request variables properly?

我正在使用NodeJS和Express開發RESTful API。
我注意到傳入的請求有時缺少一些預期的變量,這會導致程序崩潰,並說它無法將變量的值設置為'undefined'值-因為沒有值隨請求到達。
例:
該應用程序期望使用variableY,但是正在發送variableX:

 formData: { variableX: 'valueX' }

該程序希望接收variableY,其代碼如下:

const checkVariables = Joi.validate({ 
    variableY: req.body.variableY,
}, schema);

應用程序因以下錯誤而崩潰:

TypeError: Cannot read property 'variableY' of undefined

我考慮了幾種處理方法,包括在應用程序啟動時聲明變量,以及使用try-catch一起使用它們。
另一種方法是使用if-elseif-chainingcase-switch ,但是正如您所理解的,我當然正在尋找實現這一目標的最簡潔的方法。
有任何想法嗎?

謝謝。

**編輯**
僅使用對象進行了開發並設法獲得了結果。 一旦嘗試到達其中的任何內部字段,該錯誤都將被拋出,例如:
if(req.body.variableY == undefined){console.log('The expected variable is undefined');} //true

驗證處理“未定義”對象內的字段時:
if(req.body.variableY.dataId == undefined){console.log('The expected variable is undefined');} //crashes
再次引發以下錯誤:
TypeError: Cannot read property 'variableX' of undefined

經過更多的挖掘之后,發現以下Stackoverflow線程:
如何使用保存屬性名稱的變量檢查對象屬性是否存在?
使用hasOwnProperty進行了嘗試,但引發了相同類型的錯誤:
TypeError: Cannot read property 'hasOwnProperty' of undefined

嘗試使用try-catch包裝變量聲明,但仍然無法正常工作:

try{
    var variableX = req.body.variableX
    var variableXDataId = req.body.variableX.dataId
}
catch(e){
    res.status(400).send('Wrong request error: Please check your request variables and try again');
}

由於這是大多數RESTful API都應解決的非常基本的驗證(驗證您是否在請求中獲得了預期的傳入變量,因此該程序不會因無法處理的錯誤而崩潰-常見的問題解決此類問題(預期/意外請求驗證)的解決方案?

謝謝。

你可以采取另一種方法,檢查req.body你到達之前checkVariables

let body = req.body;

// data - your req.body
// requiredKeys - is an array of strings , [ key1, key2 ... keyN]  | string[]

     const setKeys = ( data, requiredKeys )=>{

         if( !typeof requiredKeys.length ){
            requiredKeys = [];
         }

         if(requiredKeys.length) requiredKeys.forEach( k =>{

             k = k.replace(/\+/g,'/');

             let keysList = [];

             if( /\/+/g.test(k)){
               keysList = k.split('/');
             }else{
              keysList = [k];
             }

             let [firstKey, ...rest] = keysList;

             if( typeof data[firstKey] === 'undefined' ){
               data[firstKey] = {};
             }

             if( rest.length ){

                data[firstKey] = setKeys(data[firstKey], [rest.join('/')] );

             }

         })

         return data;

      }

let checkedData= setKeys(body, ['variableT','variableP/noname/emptyObj','custom/object/does/not/exist/but/it/will/be/created/here']);

const checkVariables = Joi.validate(checkedData, schema);

UPDATE

在下面,您將找到一個工作示例,說明在/ (假設/ usersStatus /:id)請求期間事情如何工作:

 const express = require('express') const app = express() const port = 3000 const setKeys = (data, requiredKeys) => { if (!typeof requiredKeys.length) { requiredKeys = []; } if (requiredKeys.length) requiredKeys.forEach(k => { k = k.replace(/\\+/g, '/'); let keysList = []; if (/\\/+/g.test(k)) { keysList = k.split('/'); } else { keysList = [k]; } let [firstKey, ...rest] = keysList; if (typeof data[firstKey] === 'undefined') { data[firstKey] = {}; } if (rest.length) { data[firstKey] = setKeys(data[firstKey], [rest.join('/')]); } }) return data; } /** * Mock some data */ const getUserData = (req, res, next) => { if (typeof req.body === 'undefined') { req.body = {}; } req.body = { variableY: { someName: 23 }, variableZ: { name: 3, type: { id: 5, typeName: 'something', tags: ['a', 'b', 'c'] } } }; console.log('Middleware 1 getUserData'); next(); } /** * 1. Setup our middleware for checking keys * "requiredKeys" is an array of strings */ const middlewareSetKeys = (requiredKeys, wrappedMiddleware) => { return (req, res, next) => { console.log('Middleware 2 middlewareSetKeys'); if (typeof req.body === "undefined") { console.log('Leaving Middleware 2 since we don\\'t have req.body'); next(); } /** * Update "req.body" with keys that we want to have available * in our next middleware */ req.body = setKeys(req.body, requiredKeys); if (typeof wrappedMiddleware === 'function') { return wrappedMiddleware.call(this, req, res, next); } else { next(); } } } /** * 2. Let's assume a "user status" situation * 2.1. We need userInfo from database * 2.2. Some info won't be retrieved, unless the user accesed some parts of the website to trigger some mechanisms that allows those fields to be exposed, therefore the lack of keys * 2.3. But we know those keys/objects, and we still want to be present so our code won't crash. */ // lets call our getUserData app.get( '/', // this path is for some userInfo getUserData, // this returns userInfo and appends it to `req.data` middlewareSetKeys([ 'userActivity/daily/jobs', // these won't exist in getUserData because the user is lazy and he didn't apply for any JOBS 'userStatus/active/two-weeks-ago', // these won't exist in getUserData because the user joined two days ago. BUT WE STILL NEED IT coz reazons. ]), // We set our desired-later-to-use keys (req, res, next) => { /** * 3. Now our req.body will have our keys * even if they didn't exist in the getUserData middleware */ console.log('Middleware 3 Your middleware'); console.log(req.body); res.setHeader('Content-Type', 'application/json'); res.send(JSON.stringify(req.body, null, 2)) }) app.listen(port, () => console.log(`Example app listening on port ${port}!`)) 

您可以使用快遞驗證器https://www.npmjs.com/package/express-validator驗證傳入請求。然后將其添加到控制器中,其中a,b,c,d是您要驗證的參數

 const nonEmptyFields = ['a', 'b', 'c', 'd']; nonEmptyFields.forEach(field => req.assert(field, `${field} cannot be blank`).notEmpty()); const errors = req.validationErrors(); if (errors) { return res.status(400).send(errors); } 

用於驗證字段內的字段,您可以嘗試執行此操作

typeof(req.body && req.body.name !== undefined)

一個解決方案是設置一個默認的空對象,以替換父級的undefined:

// checking for body.variableX.variableZ with object destructuring ES6
const {body = {}} = request;
const {variableX = {}, variableY} = body;
const {variableZ} = variableX.variableZ;

// or prior ES6
var body = request.body || {};
var variableX = body.variableX || {};
var variableY = variableX.variableY;

// or in a statement
var variableY = request.body && request.body.variableX ? request.body.variableX.variableY : undefined;

基於此,您可以創建自己的函數,如getValue(request, 'body.variableX.variableY') ,如果未定義任何父項或最終值,則返回null:

// asumes the value in the path is either object or undefined
function getValue(rootObj, path = '') {
    const parts = key.split('.');
    let value = rootObj || {};
    let part;
    while ((part = parts.shift()) && value !== null) {
        value = value[part] || null;
    }
    return value;
};

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM