Skip to content

Instantly share code, notes, and snippets.

@gimenete
Last active February 28, 2017 14:43
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gimenete/3ee8564927d89cc645ab to your computer and use it in GitHub Desktop.
Save gimenete/3ee8564927d89cc645ab to your computer and use it in GitHub Desktop.
Validate input parameters in node.js requests
var _ = require('underscore')
var util = require('util')
function validate(request) {
var errors = []
var values = {}
var obj = {}
function validator(param) {
var vals = request[param]
var self = {}
self.string = function(field, required) {
var value = vals[field]
if ((_.isUndefined(value) && required) || !_.isString(value)) {
errors.push({ field: field, message: util.format('`%s` is a required string field', field) })
} else {
values[field] = value
}
return obj
}
self.stringArray = function(field, required) {
var value = vals[field]
if ((_.isUndefined(value) && required) || !_.isArray(value)) {
errors.push({ field: field, message: util.format('`%s` is a required array of strings', field) })
return obj
}
if (!_.find(value, function(val) {
if (!_.isString(val)) {
errors.push({ field: field, message: util.format('`%s` must be an array of strings', field) })
return true
}
})) {
values[field] = value
}
return obj
}
self.number = function(field, required, min, max) {
var value = vals[field]
if (value != +value) {
errors.push({ field: field, message: util.format('`%s` must be a number', field) })
return obj
}
if (_.isUndefined(value) && required) {
errors.push({ field: field, message: util.format('`%s` is a required number', field) })
return obj
}
value = +value
if (!_.isUndefined(min) && value < min) {
errors.push({ field: field, message: util.format('`%s` must be higher than %d', field, min) })
} else if (!_.isUndefined(max) && value > max) {
errors.push({ field: field, message: util.format('`%s` must be lower than %d', field, max) })
} else {
values[field] = +value
}
return obj
}
self.integer = function(field, required, min, max) {
var value = vals[field]
if (value != Math.floor(+value)) {
errors.push({ field: field, message: util.format('`%s` must be an integer', field) })
return obj
}
if (_.isUndefined(value) && required) {
errors.push({ field: field, message: util.format('`%s` is a required integer', field) })
return obj
}
value = Math.floor(+value)
if (!_.isUndefined(min) && value < min) {
errors.push({ field: field, message: util.format('`%s` must be higher or equal than %d', field, min) })
} else if (!_.isUndefined(max) && value > max) {
errors.push({ field: field, message: util.format('`%s` must be lower or equal than %d', field, max) })
} else {
values[field] = +value
}
return obj
}
self.object = function(field, required) {
var value = vals[field]
if (!_.isObject(value)) {
if (required) {
errors.push({ field: field, message: util.format('`%s` is a required string field', field) })
return obj
}
} else {
values[field] = value
}
return obj
}
return self
}
;['body', 'query', 'params'].forEach(function(key) {
obj[key] = validator(key)
})
obj.end = function(callback) {
callback(errors.length > 0 ? _.groupBy(errors, function(err) {
var field = err.field
delete err.field
return field
}) : null, values)
}
return obj
}
// example
validate(req)
.body.string('some-string-param', true)
.body.stringArray('some-array-param', true)
.body.number('a-number-param', true)
.body.integer('an-integer-param', true, 0, 100)
.end(function(errors, values) {
// errors: validation errors if any
// values: object with accepted values
console.log('errors', errors, values)
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment