繁体   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