Node.js、Express、Mongoose-输入验证-在路线或模型内?
我有一个接受JSON post的RESTAPI资源。例如:Node.js、Express、Mongoose-输入验证-在路线或模型内?,node.js,validation,express,mongoose,Node.js,Validation,Express,Mongoose,我有一个接受JSON post的RESTAPI资源。例如: { "location": { "coordinates": [ -122.41941550000001, 37.7749295 ] } 然后通过Express从请求中收集坐标: module.exports.create = function(req, res, next) { var coordinates = req.body.location.coordinates;
{
"location": {
"coordinates": [
-122.41941550000001,
37.7749295
]
}
然后通过Express从请求中收集坐标:
module.exports.create = function(req, res, next) {
var coordinates = req.body.location.coordinates;
....
然后将其提交给猫鼬模型。我正在写一个位置坐标缺失的测试
{
"foo": {
"bar": [
-122.41941550000001,
37.7749295
]
}
然后在模型的验证部分失败,原因是:
locationSchema.path('location.coordinates').validate(function(coordinates){
^
TypeError: Cannot call method 'validate' of undefined
所以我的问题是如何验证输入是否正确?这应该在到达模型前的路线中完成,还是应该在模型中完成?如有任何关于如何操作的示例,我们将不胜感激。
作为参考,Mongoose模型如下所示:
var locationSchema = new Schema({
userid: { type: Number, required: true },
location: {
type: [{
type: "String",
required: true,
enum: ['Point', 'LineString', 'Polygon'],
default: 'Point'
}], required: true,
coordinates: { type: [Number], required:true }
},
create_date: { type: Date, default: Date.now }
});
locationSchema.path('location.coordinates').validate(function(coordinates){
...
}, 'Invalid latitude or longitude.');
在我看来,验证应该在一开始就进行,首先在客户机上进行,然后在路由中进行 人们对传递无效数据、免费使用资源没有多大兴趣,因此越早将其标记为无效,就越早释放资源 要检查坐标是否存在,可以使用:
if(req.body.location.coordinates){
//do your thing
}
我的典型方法是在路由和模型之间引入服务层,这就是进行验证的地方。不要认为“服务”是“web服务”的意思;它只是围绕给定域提供了一个抽象级别。这有以下好处:
- 它为您提供了处理持久化和/或外部数据的通用抽象。也就是说,无论您是与来自Mongoose的数据交互还是与外部web服务交互,您的所有路由逻辑都可以简单地与一致的接口交互
- 它围绕持久性细节提供了完善的封装,允许您在不影响所有路由的情况下交换实现
- 它允许您对非路由使用者(如集成测试套件)重复使用代码
- 它提供了一个很好的模拟层(例如,用于单元测试)
- 它提供了一个非常清晰的“验证和业务逻辑在此发生”层,即使您的数据分布在多个不同的数据库和/或后端系统中
定位服务.js
var locationService = module.exports = {};
locationService.saveCoordinates = function saveCoordinates(coords, cb) {
if (!isValidCoordinates(coords)) {
// your failed validation response can be whatever you want, but I
// like to reserve actual `Error` responses for true runtime errors.
// the result here should be something your client-side logic can
// easily consume and display to the user.
return cb(null, {
success: false,
reason: 'validation',
validationError: { /* something useful to the end user here */ }
});
}
yourLocationModel.save(coords, function(err) {
if (err) return cb(err);
cb(null, { success: true });
});
};
app.post('/coordinates', function(req, res, next) {
var coordinates = req.body.location.coordinates;
locationService.saveCoordinates(coordinates, function(err, result) {
if (err) return next(err);
if (!result.success) {
// check result.reason, handle validation logic, etc.
} else {
// woohoo, send a 201 or whatever you need to do
}
});
});
一些路由文件.js
var locationService = module.exports = {};
locationService.saveCoordinates = function saveCoordinates(coords, cb) {
if (!isValidCoordinates(coords)) {
// your failed validation response can be whatever you want, but I
// like to reserve actual `Error` responses for true runtime errors.
// the result here should be something your client-side logic can
// easily consume and display to the user.
return cb(null, {
success: false,
reason: 'validation',
validationError: { /* something useful to the end user here */ }
});
}
yourLocationModel.save(coords, function(err) {
if (err) return cb(err);
cb(null, { success: true });
});
};
app.post('/coordinates', function(req, res, next) {
var coordinates = req.body.location.coordinates;
locationService.saveCoordinates(coordinates, function(err, result) {
if (err) return next(err);
if (!result.success) {
// check result.reason, handle validation logic, etc.
} else {
// woohoo, send a 201 or whatever you need to do
}
});
});
目前,我已经将此结构应用于3到4个不同的web应用程序和API,并且已经非常喜欢它。谢谢您的评论。那么,我如何验证路由中的输入?您想验证坐标是否为数字,还是仅验证
req.body.location.coordinates
是否存在?不。。。客户端验证与此无关。客户端验证对于用户来说很方便,但是在安全性方面没有提供任何东西,因为用户可以禁用它。第一层验证可以避免发送半填的表单、不正确的地址等…@xShirase-如果存在的话。一定要将其保存为代码段@jmar777-这非常有用。在我的应用程序中引入抽象层很有意义。谢谢你花时间分享你的想法,这对我帮助很大!