diff --git a/API.md b/API.md index c10583936..c8a73e232 100755 --- a/API.md +++ b/API.md @@ -2148,10 +2148,10 @@ following options: expressed as one of: - `true` - any payload allowed (no validation performed). This is the default. - `false` - no payload allowed. - - a [Joi](http://github.com/hapijs/joi) validation object. + - a [Joi](http://github.com/hapijs/joi) validation object. This will receive the request's headers, params, query, payload, and auth credentials and isAuthenticated flags as context. - a validation function using the signature `function(value, options, next)` where: - `value` - the object containing the response object. - - `options` - the server validation options. + - `options` - the server validation options, merged with an object containing the request's headers, params, payload, and auth credentials object and isAuthenticated flag. - `next(err)` - the callback function called when validation is completed. - `status` - HTTP status-code-specific validation rules. The `status` key is set to an object where each key is a 3 digit HTTP status code and the value has the same diff --git a/lib/validation.js b/lib/validation.js index 17e7547c6..de9d55c2e 100755 --- a/lib/validation.js +++ b/lib/validation.js @@ -194,12 +194,27 @@ exports.response = function (request, next) { return next(Boom.badImplementation(err.message)); }; + var localOptions = { + context: { + headers: request.headers, + params: request.params, + query: request.query, + payload: request.payload, + auth: { + isAuthenticated: request.auth.isAuthenticated, + credentials: request.auth.credentials + } + } + }; + + Hoek.merge(localOptions, request.route.settings.response.options); + if (typeof schema !== 'function') { - return Joi.validate(source, schema, request.route.settings.response.options, postValidate); + return Joi.validate(source, schema, localOptions, postValidate); } request._protect.run('validate:response', postValidate, function (exit) { - return schema(source, request.route.settings.response.options, exit); + return schema(source, localOptions, exit); }); }; diff --git a/test/validation.js b/test/validation.js index 3acc281db..cba231645 100755 --- a/test/validation.js +++ b/test/validation.js @@ -753,6 +753,43 @@ describe('validation', function () { }); }); + it('validates response with context', function (done) { + + var i = 0; + var handler = function (request, reply) { + + return reply({ some: 'thing', more: 'stuff' }); + }; + + var server = new Hapi.Server({ debug: false }); + server.connection(); + server.route({ + method: 'GET', + path: '/', + config: { + response: { + schema: Joi.object({ + some: Joi.string(), + more: Joi.string() + }).when('$query.user', { is: 'admin', otherwise: Joi.object({ more: Joi.forbidden() }) }) + } + }, + handler: handler + }); + + server.inject('/?user=admin', function (res) { + + expect(res.statusCode).to.equal(200); + expect(res.payload).to.equal('{"some":"thing","more":"stuff"}'); + + server.inject('/?user=test', function (res) { + + expect(res.statusCode).to.equal(500); + done(); + }); + }); + }); + it('validates error response', function (done) { var i = 0;