Serverless API离线测试:Post请求MongoDB触发字段验证错误
问题分析与解决方案
核心问题
触发验证错误的原因很明确:请求体解析方式错误。你通过Postman发送的是Content-Type: application/json格式的请求,但在handler中使用了querystring.decode()——这个方法仅适用于解析application/x-www-form-urlencoded类型的表单数据,对JSON字符串解析后会得到空对象或undefined的字段,导致mongoose无法获取到name、email、password的值,触发必填字段验证失败。
另外还有一个潜在问题:你的User Schema中未定义apiKey字段,即使解析成功,这个字段也不会被存入MongoDB,需要补充到schema中。
具体修改步骤
1. 替换请求体解析逻辑
把querystring.decode(event.body)替换为JSON.parse(event.body),同时添加异常处理,避免非法JSON请求导致崩溃:
/* Create User*/ module.exports.create = (event, context, callback) => { context.callbackWaitsForEmptyEventLoop = false; Database.connectToDatabase() .then(() => { let body; try { // 解析JSON格式的请求体 body = JSON.parse(event.body); } catch (parseErr) { return callback(null, { statusCode: 400, headers: { "Content-Type": "text/plain" }, body: "Invalid JSON format in request body", }); } console.log(event.body); const randomKey = uuidv4(); let newUser = new User({ name: body.name, email: body.email, password: body.password, apiKey: randomKey.replace(/-/g, ""), }); newUser.save(function (err, user) { if (err) { callback(null, { statusCode: err.statusCode || 500, headers: { "Content-Type": "text/plain" }, body: err.message, }); } else { callback(null, { statusCode: 200, body: JSON.stringify(user), }); } }); }) .catch((err) => { callback(null, { statusCode: err.statusCode || 500, headers: { "Content-Type": "text/plain" }, body: err.message, }); }); };
2. 补充User Schema中的apiKey字段
在你的mongoose Schema中添加apiKey字段,确保它能被存入数据库:
const userSchema = new mongoose.Schema( { email: { type: String, trim: true, required: true, unique: true, validate(value){ if(!validator.isEmail(value)){ throw new Error ("Please enter correct email"); } } }, name: { type: String, trim: true, required: true, }, password: { type: String, required: true, }, // 新增apiKey字段 apiKey: { type: String, required: true, unique: true, }, salt: String, role: { type: String, default: "Normal", }, created: { type: "Date", default: Date.now, }, subscription: { type: String, default: "dev", }, token: { type: String, default: "free", }, }, { collection: "Users" } // 修正原代码括号位置的语法错误 ); userSchema.post("save", function (_doc, next) { _doc.password = undefined; return next(); });
3. 可选:验证请求头的Content-Type
为了更严谨,可以在handler开头检查Content-Type是否为application/json,拒绝不符合格式的请求:
// 在Database.connectToDatabase()之前添加 if (!event.headers || event.headers['Content-Type'] !== 'application/json') { return callback(null, { statusCode: 415, headers: { "Content-Type": "text/plain" }, body: "Unsupported Media Type: Only application/json is accepted", }); }
测试验证
修改完成后,用你提供的curl请求再次测试,应该能成功创建用户并将数据(包括apiKey)存入MongoDB,返回200状态码和用户信息(password字段会被post-save钩子移除)。
内容的提问来源于stack exchange,提问作者MaxxABillion
相关产品推荐
相关产品推荐

