2014-10-08 12 views
5

Mam odpocząć api zasobów, które akceptuje post JSON. Przykład:Node.js, Express, Mongoose - sprawdzanie danych wejściowych - w trasie lub modelu?

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

Współrzędne następnie z żądanie Express:

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

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

Następnie są przedstawione wzorem grandidieri. Piszę testy przeciwko temu, gdy brakuje współrzędnych location.coordinates, np.

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

To wtedy się nie powiedzie w sekcji walidacji modelu z:

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

Więc moje pytanie brzmi: w jaki sposób mogę potwierdzić, że wejście jest poprawna? Czy należy to zrobić na trasie przed dostaniem się do modelu, czy też powinno to być zrobione w modelu? Dowolne przykłady tego są również mile widziane.

Dla porównania model Mongoose wyglądał:

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

Odpowiedz

6

Moje typowy podejście jest wprowadzenie warstwy usług pomiędzy trasami i modelu, a to gdzie walidacja dzieje. Nie myśl "usługi" w sensie "usługi sieci web"; po prostu zapewnia poziom abstrakcji wokół danej domeny. Ma to następujące zalety:

  • Daje to wspólną abstrakcję do radzenia sobie z utrzymującymi się i/lub zewnętrznymi danymi. To znaczy, czy wchodzisz w interakcję z danymi z Mongoose lub z zewnętrzną usługą sieciową, cała twoja logika trasy może po prostu wchodzić w interakcje ze spójnym interfejsem.
  • Zapewnia on hermetyzację dźwięku wokół szczegółów trwałości, umożliwiając zamianę implementacji bez wpływania na wszystkie trasy.
  • Umożliwia ponowne użycie kodu z użytkownikami niezwiązanymi z trasą (takimi jak pakiet testów integracji).
  • Zapewnia dobrą warstwę do kpienia (na przykład do testów jednostkowych).
  • Zapewnia bardzo przejrzystą warstwę "walidacji i logiki biznesowej dzieje się tutaj", nawet gdy dane są rozproszone w kilku różnych bazach danych i/lub systemach zaplecza.

Oto uproszczony przykład, co to może wyglądać następująco:

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 
     } 
    }); 
}); 

mam stosować tę strukturę do 3 lub 4 diff erentowe aplikacje internetowe i interfejsy API w tym momencie i całkiem im się to podobało.

+0

Zdecydowanie zapisuję to jako urywek! – xShirase

+0

@ jmar777 - to bardzo pomocne. Wprowadzenie tej warstwy abstrakcji ma sens w całej mojej aplikacji. Dzięki za poświęcenie czasu na podzielenie się swoimi przemyśleniami, to bardzo mi pomogło! – Ben

0

moim zdaniem walidacja powinna pojawić się na samym początku, na kliencie na początku, potem w trasie.

Nie ma większego zainteresowania przekazywaniem nieprawidłowych danych, używaniem zasobów za darmo, więc im szybciej oznaczysz je jako nieprawidłowe, tym szybciej zwolnisz zasoby.

sprawdzić istnienie swoich współrzędnych, można użyć:

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

Dzięki za komentarze. Jak więc sprawdzić poprawność danych wejściowych na trasie? – Ben

+0

Czy chcesz sprawdzić, czy współrzędne są liczbą, czy po prostu istnieje 'req.body.location.coordinates'? – xShirase

+0

Nooo ... sprawdzanie poprawności klienta nie ma z tym nic wspólnego. Sprawdzanie poprawności klienta jest wygodne dla wygody użytkownika, ale oferuje * nic * pod względem bezpieczeństwa, ponieważ użytkownik może go wyłączyć. – jmar777

Powiązane problemy