Each App
has its own Ajv validator instance which you can receive by App#getValidator
.
Ajv
constructor options may be provided through options.validator
option of App
constructor.
Validation & Sanitization as well as Filtering of request / response data can be described with Route#validate
, Route#acceptsContentType
and Route#respondsWith
methods respectively.
const Service = require('serviser');
const RequestError = Service.error.RequestError;
//let 'route' be a valid Route object (see routing tutorial)
//describe data format of success response (200)
route.respondsWith({
type: 'array',
additionalProperties: false,
items: {
type: 'object',
additionalProperties: false,
properties: {
id : {type : 'integer'},
email : {type : 'string'}
}
}
});
//describe one of possible error states:
//this will be picked up eg.: when generating API documentation & client SDKs
route.respondsWith(RequestError);
//or by being more specific:
route.respondsWith(new RequestError({apiCode: 'user-not-found'}));
//validate input req data
route.validate({
//ajv schema definition
additionalProperties: false, // will remove any unsupported query parameters
properties: {
limit: {type: 'integer'},
offset: {type: 'integer'},
}
}, 'query'); // possible targets: query | body | params | headers
//define accepted content-types
route.acceptsContentType('application/json');
route.main(function(req, res) {
return fetchUsersInSomeWay(req.query).then(function(users) {
// The filter method will make sure the response body has only
// those data properties which are defined in `respondsWith` schema
res.filter(users).json();
});
});
All the validation definitions get included in generated API documentation - see serviser-doc plugin.
Single error vs All validation failures in request response
By default, the route.validate
middleware will respond with ValidationError
immediately the first validation failure is encountered.
if a report of all validation failures is desired, you can make use of application wide configuration of Ajv
with option allErrors=true
:
service.buildApp('app-name', {validator: {allErrors: true}});
... in which case the validation middleware will respond with ValidationCompoundError
instead.
Customizing response data format
These are the default response data formats for
ValidationError
:
{
"message": ".email should match format `email`",
"code": 400,
"api_code": "validationFailure",
"uid": null
}
ValidationCompoundError
:
{
"message": "One or more validation failures have been encountered.",
"code": 400,
"api_code": "validationFailure",
"failures": [
{
"dataPath": ".email",
"message": "should match format `email`"
}
],
"uid": null
}
if you want your application to respond with different data format, you will need to override ValidationError#toJSON
implementation by creating a new error constructor which inherits from the ValidationError
:
const Service = require('serviser');
const ValidationError = Service.error.ValidationError;
/**
*
* @param {Object} context
* @param {String} context.keyword
* @param {String} context.dataPath
* @param {String} context.schemaPath
* @param {Object} context.params
* @param {Object} context.parentSchema
* @param {mixed} context.data
* @param {String} context.message
* @constructor
* @extends {ValidationError}
**/
function CustomValidationError(context) {
ValidationError.call(this, context);
}
//custom constructor must inherit from serviser's `ValidationError`
CustomValidationError.prototype = Object.create(ValidationError.prototype);
CustomValidationError.prototype.constructor = CustomValidationError;
//override toJSON implementation
CustomValidationError.prototype.toJSON = function toJSON() {
return {
api_code : this.apiCode,
code : this.code,
message : this.message,
uid : this.uid
};
};
//you may also want to override `toSwagger` & `toLogger` methods so that
//documentation will get correctly rendered and internal errors will get
//logged in correct format respectively
//all you need to do then is to tell the app's validator to instantiate different error objects
const validator = service.appManager.get('app-name').getValidator();
validator.ValidationErrorConstructor = CustomValidationError;
Next: Logging tutorial.