node manejo example español errores node.js validation mongodb mongoose

node.js - manejo - mongoose npm



Manejo de errores de validación de Mongoose: ¿dónde y cómo? (6)

A partir de mongoose 4.5.0 Document # invalidate devuelve ValidationError. Ver esto https://github.com/Automattic/mongoose/issues/3964

Además, al intentar invalidar en un hook de consulta findOneAndUpdate, puede hacer:

// pass null because there is no document instance let err = new ValidationError(null) err.errors[path] = new ValidatorError({ path: ''postalCode'', message: ''postalCode not supported on zones'', type: ''notvalid'', value, }) throw(err)

Estoy tratando de decidir cómo quiero manejar los errores de validación en Mongoose.

Mensajes de error personalizados que utilizan el nodo-validador

Definí mis propias reglas de validación usando node-validator , por ejemplo:

UserSchema.path(''username'') .validate(function (username) { return validator.check(username).notEmpty() }, ''Username cannot be blank'')

Lo cual generará un error que se ve así:

username: { message: ''Validator "Username cannot be blank" failed for path username'', name: ''ValidatorError'', path: ''username'', type: ''Username cannot be blank'' },

Usando mangosta-validador

Sin embargo, el nodo-validador proporciona sus propios mensajes de error. Si uso el módulo Nodo mongoose-validator para conectar node-validator directamente en mi esquema, entonces puedo usar estos mensajes de error directamente en su lugar:

var UserSchema = new Schema({ name: { type: String, validate: [validate(''notEmpty'')] } });

Lo cual generará un mensaje de error que se ve así:

name: { message: ''Validator "String is empty" failed for path name'', name: ''ValidatorError'', path: ''name'', type: ''String is empty'' } }

También puedo proporcionar un mensaje de error personalizado aquí:

var UserSchema = new Schema({ name: { type: String, validate: [validate({message: ''Name cannot be blank'' }, ''notEmpty'')] } });

Mongoose required bandera

Mongoose te permite definir un campo según sea necesario:

var UserSchema = new Schema({ name: { type: String, required: true } });

Lo cual generará un mensaje de error que se ve así:

name: { message: ''Validator "required" failed for path name'', name: ''ValidatorError'', path: ''name'', type: ''required'' } }

La pregunta

Parece que estos validadores desean que use sus mensajes de error incorporados. Por ejemplo, quiero declarar un campo como se required como se ve arriba, pero no puedo encontrar una forma de personalizar el mensaje de error. Y el módulo de validación de mangostas no admitía mensajes personalizados hasta hace muy poco, lo que me hace pensar que son un antipatrón en el nivel del modelo.

¿Cuál es la mejor manera de implementar estos validadores? ¿Debo dejar que generen sus propios errores y luego interpretarlos de alguna manera después?


Advertencia: A partir de Mongoose 4.1.3 la firma para la función ValidatorError ha cambiado completamente y la información a continuación no es más aplicable:

A partir de Mongoose 3.8.12 la firma para la función ValidatorError es:

function ValidatorError (path, msg, type, val)

Donde el tipo puede ser "no válido" o "requerido"

Por ejemplo, si su validación de campo de "correo electrónico" genera un error de validación, simplemente puede hacer:

var error = new ValidationError(this); error.errors.email = new ValidatorError(''email'', "Your err message.", ''notvalid'', this.email);


De Mongoose: mongoose-validator

Mensajes de error Los mensajes de error personalizados ahora están de vuelta en 0.2.1 y pueden configurarse a través del objeto de opciones:

validate({message: "String should be between 3 and 50 characters"}, ''len'', 3, 50)

Cómo implementé esto:

var emailValidator = [validate({message: "Email Address should be between 5 and 64 characters"},''len'', 5, 64), validate({message: "Email Address is not correct"},''isEmail'')]; var XXXX = new Schema({ email : {type: String, required: true, validate: emailValidator} });

Mi parte delantera trata con los requeridos, por lo que no espero que el error "requerido" de la mangosta llegue al usuario, más que un protector de seguridad de fondo.


En este punto, parece lógico comprar cómo la mangosta maneja los errores.

No le gustaría que sus modelos manejen los mensajes de error. La capa de presentación (¿controladores?) Debe confiar en el type para decidir cuál es el mejor mensaje fácil de usar para mostrar (i18n considerado).

También existe el caso donde la validación puede ocurrir al usar un middleware . En este caso, el mensaje de error que aparecerá en la superficie de su controlador es lo que pase a la next() devolución de llamada.

Por lo tanto, en el caso del middleware, aunque no esté documentado, para mantener una API de validación constante en todos los modelos, debe usar directamente los constructores de errores de Mongoose:

var mongoose = require(''mongoose''); var ValidationError = mongoose.Error.ValidationError; var ValidatorError = mongoose.Error.ValidatorError; schema.pre(''save'', function (next) { if (/someregex/i.test(this.email)) { var error = new ValidationError(this); error.errors.email = new ValidatorError(''email'', ''Email is not valid'', ''notvalid'', this.email); return next(error); } next(); });

De esta manera, se le garantiza un manejo de errores de validación constante incluso si el error de validación proviene de un middleware.

Para emparejar correctamente los mensajes de error con los tipos, crearía una enumeración que actuaría como un mapa estático para todos los tipos posibles:

// my controller.js var ValidationErrors = { REQUIRED: ''required'', NOTVALID: ''notvalid'', /* ... */ }; app.post(''/register'', function(req, res){ var user = new userModel.Model(req.body); user.save(function(err){ if (err) { var errMessage = ''''; // go through all the errors... for (var errName in err.errors) { switch(err.errors[errName].type) { case ValidationErrors.REQUIRED: errMessage = i18n(''Field is required''); break; case ValidationErrors.NOTVALID: errMessage = i18n(''Field is not valid''); break; } } res.send(errMessage); } }); });


La pregunta que debe hacerse es, en primer lugar, ¿quién es el responsable de causar el error?

Si esto sucede en su sistema, sobre el que tiene control, simplemente deje que los errores lo golpeen como lo haría normalmente, y elimine los errores a medida que avanza, pero sospecho que está haciendo una aplicación que está enfrentando usuarios del mundo real y quieres desinfectar sus entradas.

Recomendaría que en el lado del cliente compruebe que la entrada sea correcta antes de enviarla a su servidor, y muestre buenos mensajes de ayuda como "Su nombre de usuario debe estar entre los caracteres xey".

Luego, en el lado del servidor, espera que en el 99% de los casos, la entrada provenga directamente de su cliente desinfectante, por lo que aún la valida utilizando las técnicas que ya ha sugerido, pero si hay un error simplemente devuelve un mensaje de error general a la interfaz de usuario, ya que confía en que su interfaz de usuario habría mostrado mensajes de ayuda, por lo que el error de validación debe ser causado por un error o un intento de piratería.

Recuerde registrar todos los errores de validación del lado del servidor, ya que podrían ser errores graves o alguien que busque vulnerabilidades.


Sé que los complementos de validación probablemente sean útiles, pero creo que la validación de la mangosta es más intimidante de lo que realmente es complicado. Definitivamente se ve complicado desde el exterior, pero una vez que empiezas a desgarrarlo, no es tan malo.

Si revisa el siguiente código, verá un ejemplo de cómo se puede devolver un mensaje de error personalizado utilizando validadores incorporados.

Todo lo que tiene que hacer es establecer un segundo parámetro, con su propio mensaje de error personalizado, al configurar sus campos.

maxlength campos required minlength y maxlength continuación para ver cómo configuré un mensaje de error personalizado, y luego revise los métodos a continuación sobre cómo se puede acceder al objeto de error o enviarlo a la interfaz:

// Grab dependencies: var mongoose = require(''mongoose''); // Setup a schema: var UserSchema = new mongoose.Schema ( { username: { type: String, minlength: [2, ''Username must be at least 2 characters.''], maxlength: [20, ''Username must be less than 20 characters.''], required: [true, ''Your username cannot be blank.''], trim: true, unique: true, // username must be unique dropDups: true, }, // end username field }, { timestamps: true, }, ); // Export the schema: module.exports = mongoose.model(''User'', UserSchema);

Lo anterior configura nuestros campos para tener mensajes de error personalizados. ¿Pero cómo accedemos a ellos o los enviamos a nuestra interfaz? Podríamos tener la siguiente configuración de método en nuestro controlador de servidor, cuyos datos de respuesta se envían nuevamente a angular:

var myControllerMethods = { register : function(req, res) { // Create a user based on the schema we created: User.create(req.body) .then(function(newUser) { console.log(''New User Created!'', newUser); res.json(newUser); }) .catch(function(err) { console.log(''Error Validating!'', err); res.status(500).json(err); }) }, };

Si ejecutó el código anterior y ninguno de nuestros validadores de mangosta no pasó, el objeto de error ( err ) será capturado por .catch() en la promesa. Si la consola registra este error, verá que ese objeto es nuestro mensaje personalizado, según el error que se marcó.

Nota: El ejemplo anterior es solo para agregar mensajes de validación personalizados a las validaciones ya incorporadas que posee Mongoose (como required , minlength , maxlength , etc.).

Si desea crear validaciones más avanzadas, como la validación de campos contra patrones de expresiones regulares o similares, tendrá que crear funciones de validator personalizadas.

Consulte la sección "Validadores personalizados" en este enlace para obtener un excelente ejemplo de cómo agregar un validador directamente en su campo: http://mongoosejs.com/docs/validation.html .

Nota: También puede usar "ganchos de guardado previo" y "métodos de instancia", pero esto va más allá del alcance de esta pregunta y los validadores incorporados y los "Validadores personalizados" (enlace mencionado anteriormente) son rutas más fáciles.

¡Espero que esto ayude!