Skip to content

Commit

Permalink
added validateResponse middleware
Browse files Browse the repository at this point in the history
  • Loading branch information
nrstott committed Dec 6, 2011
1 parent da32c85 commit ff789b5
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 3 deletions.
3 changes: 2 additions & 1 deletion README.md
Expand Up @@ -87,7 +87,8 @@ want to use them.
The batteries middleware creates the following JSGI chain where `nextApp` is the JSGI appliance passed as the first parameter
to `batteries`:

error - directory - parted - methodOverride - session - flash - bodyAdapter - stringReturnAdapter - nextApp
error -> validateResponse -> directory -> parted -> methodOverride
-> session -> flash -> bodyAdapter -> stringReturnAdapter -> nextApp

The binary middleware is configured to check the path of the request and if it corresponds to a potential directory in the 'public' directory,
the request is routed to the `directory` middleware to serve a static file.
Expand Down
46 changes: 44 additions & 2 deletions lib/middleware.js
Expand Up @@ -151,7 +151,8 @@ exports.parted = exports.Parted = function(nextApp, opts) {
/**
* Translates rejected promises to a JSGI error response.
*
* @param errorResponse {Function} A function that returns a JSGI response when passed an error.
* @param errorResponse {Function} Optional. A function that returns a JSGI response when passed an error.
* @returns {Function} JSGI response.
*/
exports.error = exports.Error = function(app, errorResponse) {
errorResponse = errorResponse ||
Expand Down Expand Up @@ -180,6 +181,45 @@ exports.error = exports.Error = function(app, errorResponse) {
};
};

/**
* Validates that the response from nextApp is a valid JSGI response.
* Rejects the promise if the response is invalid.
*
* @param {Function} nextApp The next application in the JSGI chain.
* @returns {Function} JSGI response.
*/
exports.validateResponse = exports.ValidateResponse = function(nextApp) {
return function(req) {
return when(nextApp(req), function(resp) {
if (!resp) {
throw 'Response must be an object.'
}

if (!resp.body) {
throw 'Response must have a body property.'
}

if (!resp.body.forEach) {
throw 'Response body must have a forEach method.';
}

if (typeof resp.body.forEach !== 'function') {
throw 'Response body has a forEach method but the forEach method is not a function.'
}

if (!resp.status) {
throw 'Response must have a status property.';
}

if (typeof resp.status.constructor !== '[Function: Number]') {
throw 'Response has a status property but the status property must be a number.'
}

return resp;
});
};
};

var HTTP_METHODS = exports.HTTP_METHODS = {
"GET": true,
"HEAD": true,
Expand Down Expand Up @@ -569,7 +609,9 @@ exports.binary = function(conditional, appTrue, appFalse) {
* All the goodies in one convenient middleware.
*
* Includes the following JSGI Chain:
* error - directory - parted - methodOverride - session - flash - bodyAdapter - stringReturnAdapter - nextApp
*
* error -> validateResponse -> directory -> parted -> methodOverride
* -> session -> flash -> bodyAdapter -> stringReturnAdapter -> nextApp
*
* @param {Object} config Optional configuration, if arity is two first parameter is config.
* @param {Function} nextApp The next application (Middleware, Bogart Router, etc...) in the JSGI chain.
Expand Down

0 comments on commit ff789b5

Please sign in to comment.