Skip to content

Commit

Permalink
Merge b02bc98 into 59bb9b6
Browse files Browse the repository at this point in the history
  • Loading branch information
dschenkelman committed Sep 18, 2014
2 parents 59bb9b6 + b02bc98 commit 7301f23
Show file tree
Hide file tree
Showing 4 changed files with 176 additions and 269 deletions.
16 changes: 9 additions & 7 deletions lib/RequestValidator.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@ var RequestValidator = function(plugin, options) {
onRequest = function(request, next) {
// hand routes for this server to schema manager so it can compile the schemas for each route
// this method will not attempt to compile them more than once, so this is safe to call on every request
routeSchemaManager.initializeRoutes(request.server.info.uri, request.server.table(), function(error) {
if (error) {
log('error', 'Unable to compile schemas', error);
return next(error);
}
next();
});
try {
routeSchemaManager.initializeRoutes(request.server.info.uri, request.server.table());
}
catch (error){
log('error', 'Unable to compile and validate schemas', error);
return next(error);
}

next();
},

onPreHandler = function(request, next) {
Expand Down
96 changes: 41 additions & 55 deletions lib/RouteSchemaManager.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
var ZSchema = require('z-schema'),
async = require('async'),
_ = require('underscore'),
syncValidator = new ZSchema({ sync: true }),
validator = new ZSchema();


var RouteSchemaManager = function(options) {
options = options || {};

var compiledSchemasByServerUri = {},
var schemasByServerUri = {},
validationTypes = {
PATH: 'path',
QUERY: 'query',
Expand Down Expand Up @@ -66,32 +63,37 @@ var RouteSchemaManager = function(options) {
return modifiedSchema;
},

compileSchemasForRoute = function(route, callback) {
var compileFuncs = {};
generateSchemasForRoute = function(route) {
var schemas = {};
forEachValidationOption(route, function(validationOption, validationType) {
var validationSchema = (validationType === validationTypes.RESPONSE) ?
validationOption.schema :
(validationType === validationTypes.HEADERS) ?
modifyHeadersSchema(validationOption) :
validationOption;
(function(key, schema) {
compileFuncs[key] = function(cb) {
validator.compileSchema(schema, cb);
};
}(constructSchemaKey(validationType, route.method, route.path), validationSchema));

var schemaKey = constructSchemaKey(validationType, route.method, route.path);

if (!validator.validateSchema(validationSchema)){
throw new Error('Failed to validate schema for route ' + route.path +
' method ' + route.method +
' type ' + validationType);
}

schemas[schemaKey] = validationSchema;
});

async.parallel(compileFuncs, callback);
return schemas;
},

getCompiledSchemasForRoute = function(route) {
getSchemasForRoute = function(route) {
var schemas = null,
serverUri = route.server.info.uri;
if (compiledSchemasByServerUri[serverUri]) {
if (schemasByServerUri[serverUri]) {
forEachValidationOption(route, function(validationOption, validationType) {
schemas = schemas || {};
var key = constructSchemaKey(validationType, route.method, route.path);
schemas[validationType] = compiledSchemasByServerUri[serverUri][key];
schemas[validationType] = schemasByServerUri[serverUri][key];
});
}
return schemas;
Expand Down Expand Up @@ -167,55 +169,39 @@ var RouteSchemaManager = function(options) {
}
};

this.initializeRoutes = function(serverUri, routes, callback) {

if (!compiledSchemasByServerUri[serverUri]) {
compiledSchemasByServerUri[serverUri] = {};
var compileFuncs = [];
this.initializeRoutes = function(serverUri, routes) {
if (!schemasByServerUri[serverUri]) {
schemasByServerUri[serverUri] = {};

routes.forEach(function(route) {
(function(r) {
compileFuncs.push(function(cb) {
compileSchemasForRoute(r, cb);
});
}(route));
schemasByServerUri[serverUri] = _.extend(
schemasByServerUri[serverUri],
generateSchemasForRoute(route));
});

async.parallel(compileFuncs, function(err, results) {
if (err) {
// log?
return callback(err);
}
results.forEach(function(result) {
compiledSchemasByServerUri[serverUri] = _.extend(compiledSchemasByServerUri[serverUri], result);
});
callback();
});
}
else {
callback();
}
};

this.validatePath = function(request) {
var schemas = getCompiledSchemasForRoute(request._route);
var schemas = getSchemasForRoute(request._route);
if (!schemas || !schemas[validationTypes.PATH]) {
return { valid: true };
}
// convert path types before validating
convertPropertyTypesToMatchSchema(request.params, schemas[validationTypes.PATH]);

var report = {
valid: syncValidator.validate(request.params, schemas[validationTypes.PATH])
valid: validator.validate(request.params, schemas[validationTypes.PATH])
};

if (!report.valid) {
report.errors = syncValidator.getLastError().errors;
report.errors = validator.getLastErrors();
}

return report;
};

this.validateQuery = function(request) {
var schemas = getCompiledSchemasForRoute(request._route);
var schemas = getSchemasForRoute(request._route);
if (!schemas || !schemas[validationTypes.QUERY]) {
return { valid: true };
}
Expand All @@ -224,16 +210,16 @@ var RouteSchemaManager = function(options) {
convertPropertyTypesToMatchSchema(request.query, schemas[validationTypes.QUERY], true);

var report = {
valid: syncValidator.validate(request.query, schemas[validationTypes.QUERY])
valid: validator.validate(request.query, schemas[validationTypes.QUERY])
};
if (!report.valid) {
report.errors = syncValidator.getLastError().errors;
report.errors = validator.getLastErrors();
}
return report;
};

this.validatePayload = function(request) {
var schemas = getCompiledSchemasForRoute(request._route);
var schemas = getSchemasForRoute(request._route);
if (!schemas || !schemas[validationTypes.PAYLOAD]) {
return { valid: true };
}
Expand All @@ -247,33 +233,33 @@ var RouteSchemaManager = function(options) {
}

var report = {
valid: syncValidator.validate(request.payload, schemas[validationTypes.PAYLOAD])
valid: validator.validate(request.payload, schemas[validationTypes.PAYLOAD])
};
if (!report.valid) {
report.errors = syncValidator.getLastError().errors;
report.errors = validator.getLastErrors();
}
return report;
};

this.validateHeaders = function(request) {
var schemas = getCompiledSchemasForRoute(request._route);
var schemas = getSchemasForRoute(request._route);
if (!schemas || !schemas[validationTypes.HEADERS]) {
return { valid: true };
}
// convert header types before validating
convertPropertyTypesToMatchSchema(request.raw.req.headers, schemas[validationTypes.HEADERS], true);

var report = {
valid: syncValidator.validate(request.raw.req.headers, schemas[validationTypes.HEADERS])
valid: validator.validate(request.raw.req.headers, schemas[validationTypes.HEADERS])
};
if (!report.valid) {
report.errors = syncValidator.getLastError().errors;
report.errors = validator.getLastErrors();
}
return report;
};

this.validateResponse = function(request) {
var schemas = getCompiledSchemasForRoute(request._route);
var schemas = getSchemasForRoute(request._route);
if (!schemas || !schemas[validationTypes.RESPONSE]) {
return { valid: true };
}
Expand All @@ -282,10 +268,10 @@ var RouteSchemaManager = function(options) {
return { valid: false, errors: ['response is not an object'] };
}
var report = {
valid: syncValidator.validate(request.response.source, schemas[validationTypes.RESPONSE])
valid: validator.validate(request.response.source, schemas[validationTypes.RESPONSE])
};
if (!report.valid) {
report.errors = syncValidator.getLastError().errors;
report.errors = validator.getLastErrors();
}
return report;
};
Expand Down
9 changes: 4 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,10 @@
],
"version": "0.5.2",
"dependencies": {
"async": "0.x.x",
"z-schema": "2.x.x",
"underscore": "1.x.x",
"hoek": "2.x.x"
},
"underscore": "1.x.x",
"hoek": "2.x.x",
"z-schema": "3.x.x"
},
"devDependencies": {
"mocha": "1.x.x",
"jshint": "2.x.x",
Expand Down

0 comments on commit 7301f23

Please sign in to comment.