Node.js,Express,Mongoose – inputvalidation – 在路由或模型中?

我有一个restapi资源,接受一个JSON文章。 例:

{ "location": { "coordinates": [ -122.41941550000001, 37.7749295 ] } 

然后通过Express从请求中收集坐标:

 module.exports.create = function(req, res, next) { var coordinates = req.body.location.coordinates; .... 

然后这些提交给一个mongoose模型。 我正在写这个testing,在这个地方。坐标缺less,例如

 { "foo": { "bar": [ -122.41941550000001, 37.7749295 ] } 

然后在模型的validation部分失败:

 locationSchema.path('location.coordinates').validate(function(coordinates){ ^ TypeError: Cannot call method 'validate' of undefined 

所以我的问题是我将如何validationinput是正确的? 在进入模型之前,是否应该在路线上完成这项工作?还是应该在模型中完成? 任何例子,如何也将不胜感激。

作为参考,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.'); 

我的典型做法是在路由和模型之间引入一个服务层,这就是validation发生的地方。 不要以“networking服务”的意思来思考“服务”; 它只是提供给定域的抽象级别。 这有以下好处:

  • 它为您提供了处理持久和/或外部数据的通用抽象。 也就是说,无论您是使用Mongoose还是外部Web服务交互数据,您的所有路由逻辑都可以简单地与一致的接口进行交互。
  • 它提供了关于持久性细节的声音封装,允许您在不影响所有路由的情况下交换实现。
  • 它允许您将代码重新用于非路由使用者(例如集成testing套件)。
  • 它为模拟提供了一个很好的层(例如,用于unit testing)。
  • 它提供了一个非常清晰的“validation和业务逻辑发生在这里”层,即使您的数据分布在多个不同的数据库和/或后端系统上。

下面是可能看起来像一个简单的例子:

location-service.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 }); }); }; 

some-route-file.js

 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,并且已经非常喜欢它。

在我看来,validation应该在一开始,首先在客户端,然后在路线上进行。

没有太多的兴趣来传递无效数据,毫无用处地使用资源,所以越早将其标记为无效,越早释放资源。

要检查您的坐标的存在,您可以使用:

 if(req.body.location.coordinates){ //do your thing }