Skip to content

Commit

Permalink
Payload failAction. Closes hapijs#1314
Browse files Browse the repository at this point in the history
  • Loading branch information
Eran Hammer committed Jan 9, 2014
1 parent 5ff5af8 commit 7759c2b
Show file tree
Hide file tree
Showing 7 changed files with 63 additions and 179 deletions.
4 changes: 4 additions & 0 deletions docs/Reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,10 @@ The following options are available when adding a route:
- `override` - a mime type string overriding the 'Content-Type' header value received. Defaults to no override.
- `maxBytes` - overrides the server [default value](#server.config.payload) for this route.
- `uploads` - overrides the server [default value](#server.config.payload) for this route.
- `failAction` - determines how to handle payload parsing errors. Allowed values are:
- `'error'` - return a Bad Request (400) error response. This is the default value.
- `'log'` - report the error but continue processing the request.
- `'ignore'` - take no action and continue processing the request.

- `response` - validation rules for the outgoing response payload (response body). Can only validate [object](#obj) response. Values allowed:
- `true` - any payload allowed (no validation performed). This is the default.
Expand Down
24 changes: 21 additions & 3 deletions lib/payload.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,24 @@ exports.read = function (request, next) {
return next();
}

// Fail action

var failActionNext = function (err) {

// failAction: 'error', 'log', 'ignore'

var failAction = request.route.payload.failAction;
if (failAction !== 'ignore') {
request.log(['hapi', 'payload', 'error'], err);
}

if (failAction === 'error') {
return next(err);
}

return next();
};

// Content size

var req = request.raw.req;
Expand All @@ -45,13 +63,13 @@ exports.read = function (request, next) {
((Array.isArray(request.route.payload.allow) && request.route.payload.allow.indexOf(mime) === -1) ||
request.route.payload.allow !== mime)) {

return next(Boom.unsupportedMediaType());
return failActionNext(Boom.unsupportedMediaType());
}

// Parse: true

if (request.route.payload.parse) {
return internals.parse(request, next);
return internals.parse(request, failActionNext);
}

// Parse: false
Expand All @@ -60,7 +78,7 @@ exports.read = function (request, next) {
};


internals.parse = function (request, next) {
internals.parse = function (request, next, failActionNext) {

var output = request.route.payload.output; // Output: 'data', 'stream', 'file'
var source = request.raw.req;
Expand Down
1 change: 1 addition & 0 deletions lib/route.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ exports = module.exports = internals.Route = function (options, server, env) {
this.settings.payload.parse = (this.settings.payload.parse !== null && this.settings.payload.parse !== undefined ? this.settings.payload.parse : (isProxy ? false : true));
this.settings.payload.maxBytes = this.settings.payload.maxBytes || this.server.settings.payload.maxBytes;
this.settings.payload.uploads = this.settings.payload.uploads || this.server.settings.payload.uploads;
this.settings.payload.failAction = this.settings.payload.failAction || 'error';
}

Utils.assert(!this.settings.validate.payload || (this.settings.payload && this.settings.payload.parse), 'Route payload must be set to \'parse\' when payload validation enabled:', options.path);
Expand Down
3 changes: 2 additions & 1 deletion lib/schema.js
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,8 @@ internals.routeConfigSchema = {
allow: [Joi.string(), Joi.array()],
override: Joi.string(),
maxBytes: Joi.number(),
uploads: Joi.string()
uploads: Joi.string(),
failAction: Joi.string().valid('error', 'log', 'ignore')
}),
auth: [
Joi.object({
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "hapi",
"description": "HTTP Server framework",
"homepage": "http://hapijs.com",
"version": "2.0.0",
"version": "2.0.0-preview",
"repository": {
"type": "git",
"url": "git://github.com/spumko/hapi"
Expand Down
34 changes: 34 additions & 0 deletions test/integration/payload.js
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,28 @@ describe('Payload', function () {
});
});

it('errors on payload too big', function (done) {

var payload = '{"x":"1","y":"2","z":"3"}';

var handler = function (request, reply) {

expect(request.payload.toString()).to.equal(payload);
reply(request.payload);
};

var server = new Hapi.Server();
server.route({ method: 'POST', path: '/', config: { handler: handler, payload: { maxBytes: 10 } } });

server.inject({ method: 'POST', url: '/', payload: payload, headers: { 'content-length': payload.length } }, function (res) {

expect(res.statusCode).to.equal(400);
expect(res.result).to.exist;
expect(res.result.message).to.equal('Payload content length greater than maximum allowed: 10');
done();
});
});

it('peeks at unparsed data', function (done) {

var data = null;
Expand Down Expand Up @@ -542,6 +564,18 @@ describe('Payload', function () {
req.end('{ "key": "value" }');
});

it('ignores unsupported mime type', function (done) {

var server = new Hapi.Server();
server.route({ method: 'POST', path: '/', config: { handler: function (request, reply) { reply(request.payload); }, payload: { failAction: 'ignore' } } });
server.inject({ method: 'POST', url: '/', payload: 'testing123', headers: { 'content-type': 'application/unknown' } }, function (res) {

expect(res.statusCode).to.equal(200);
expect(res.result).to.deep.equal({});
done();
});
});

it('returns 200 on octet mime type', function (done) {

var server = new Hapi.Server();
Expand Down
174 changes: 0 additions & 174 deletions test/unit/payload.js

This file was deleted.

0 comments on commit 7759c2b

Please sign in to comment.