Node.js,Express,Mongoose - 输入验证 - 在路由或模型中?

时间:2014-10-08 22:21:10

标签: node.js validation express mongoose

我有一个接受JSON帖子的rest api资源。例如:

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

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

module.exports.create = function(req, res, next) {

    var coordinates = req.body.location.coordinates;
    ....

然后将这些提交给Mongoose模型。我正在编写测试对象,其中缺少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.');

2 个答案:

答案 0 :(得分:6)

我的典型方法是在路由和模型之间引入服务层,这就是验证发生的地方。不要在“网络服务”意义上考虑“服务”;它只是提供给定域的抽象级别。这有以下好处:

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

这是一个简单的例子:

<强> 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个不同的网络应用和API,并且已经非常喜欢它。

答案 1 :(得分:0)

在我看来,验证应该在最开始,首先在客户端,然后在路由中进行。

传递无效数据并没有太大兴趣,没有资源使用资源,所以越早将其标记为无效,就越早释放资源。

检查坐标是否存在,可以使用:

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