2014-10-08 3 views
5

У меня есть ресурс api rest, который принимает сообщение JSON. Пример:Node.js, Express, Mongoose - проверка ввода - в пределах маршрута или модели?

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

Координаты затем собирают из запроса по экспресс:

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.'); 

ответ

6

Мой типичный подход является введение уровня услуг между маршрутами и модели, а вот где проверка происходит. Не думайте «сервис» в смысле «веб-службы»; он просто обеспечивает уровень абстракции вокруг данного домена. Это имеет следующие преимущества:

  • Это дает вам общую абстракцию для работы с сохраненными и/или внешними данными. То есть, взаимодействуете ли вы с данными из Mongoose или внешней веб-службы, вся ваша маршрутная логика может просто взаимодействовать с последовательным интерфейсом.
  • Он обеспечивает звуковую инкапсуляцию вокруг деталей персистентности, позволяя вам выполнить реализацию без использования всех ваших маршрутов.
  • Он позволяет повторно использовать код с немаршрутными потребителями (например, набор тестов интеграции).
  • Он обеспечивает хороший уровень для издевательств (например, для использования с модульными тестами).
  • Он обеспечивает очень четкий уровень «валидация и бизнес-логика здесь», даже когда ваши данные распространяются по нескольким различным базам данных и/или бэкэнд-системам.

Вот упрощенный пример того, что это может выглядеть следующим образом:

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 diff и веб-приложений и API в данный момент, и полюбили его.

+0

Определенно сохраняя это как фрагмент! – xShirase

+0

@ jmar777 - это супер полезный. Представляя, что слой абстракции имеет смысл в моем приложении. Спасибо, что нашли время поделиться своими мыслями, вот что мне очень помогло! – Ben

0

На мой взгляд проверка должна происходить в самом начале, на клиенте при первом, а затем в маршруте.

Существует не так много интереса к передаче недействительных данных, используя ресурсы для ничего, поэтому, чем раньше вы укажете его как недействительный, тем скорее вы освободите ресурсы.

проверить наличие ваших координат, вы можете использовать:

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

Спасибо за комментарии. Итак, как я могу проверить вход в маршрут? – Ben

+0

Вы хотите проверить, что координаты являются числами или просто существует 'req.body.location.coordinates'? – xShirase

+0

Nooo ... проверка клиента не имеет к этому никакого отношения. Проверка клиента хороша для удобства пользователя, но предлагает * ничего * с точки зрения безопасности, так как пользователь может ее отключить. – jmar777

Смежные вопросы