Skip to content

refactors module for performance/readability #2

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
May 24, 2015
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
140 changes: 94 additions & 46 deletions lib/index.js
Original file line number Diff line number Diff line change
@@ -1,107 +1,155 @@
'use strict';

var isArray = Array.isArray;

var _ = require('lodash');
var typeis = require('type-is');
var defaults = _.defaults;

var typeis = require('type-is');

/**
* @public
* @param {object} options
* @param {boolean} [options.checkQuery]
* @param {boolean} [options.checkBody]
* @param {string} [options.checkBodyOnlyForContentType]
* @param {string[]|string} [options.whitelist]
* @return {function}
*/
module.exports = function (options) {

options = _.defaults(options || {}, {
options = defaults(options || {}, {
checkQuery: true,
checkBody: true,
checkBodyOnlyForContentType: 'urlencoded',
whitelist: null
});

if (_.isString(options.whitelist)) {
options.whitelist = [ options.whitelist ];
if (typeof options.whitelist === 'string') {
options.whitelist = [options.whitelist];
}

if (!_.isNull(options.whitelist) && !_.isArray(options.whitelist)) {
console.error('[HPP] Please pass either a string or an array to "options.whitelist". Deactivated the whitelist!');
if (options.whitelist !== null && !isArray(options.whitelist)) {
options.whitelist = null;
}

if (_.isArray(options.whitelist)) {
for ( var w = options.whitelist.length-1; w >= 0; w-=1 ) {
if (!_.isString(options.whitelist[w])) {
console.error('[HPP] Please pass only strings into the "options.whitelist" array. Removed the entry <' + String(options.whitelist[w]) + '>!');
options.whitelist.splice(w, 1);
if (isArray(options.whitelist)) {

options.whitelist = options.whitelist.filter(function (elem) {

if (typeof elem !== 'string') {

var whiteListTypeErrorMsg = [
'[HPP] ',
'Please pass only strings into the "options.whitelist" array. ',
'Removed the entry <',
String(elem),
'>!'
].join('');

console.error(whiteListTypeErrorMsg);

return false;
}
}
}

return true;
});

function correctContentType(req) {
}

/**
* @private
* @param {object} req
* @return {string}
*/
function _correctContentType(req) {
return typeis(req, options.checkBodyOnlyForContentType);
}

function fnPutAsideIn(requestPart) {
/**
* @private
* @param {string} requestPart e.g 'body' or 'query'
* @param {object} req
*/
function _putAside(requestPart, req) {
var whitelist = options.whitelist;

var polluted = requestPart + 'Polluted';

return function putAside(req) {
var reqPart = req[requestPart];
var reqPolluted = req[polluted];

// Put aside only once in case multiple HPP middlewares are used
if (_.isUndefined(req[polluted])) {
// Put aside only once in case multiple HPP middlewares are used
if (typeof reqPolluted === 'undefined') {

req[polluted] = {};
reqPolluted = req[polluted] = {};

var parameters = _.keys(req[requestPart]);
for (var i = 0; i < parameters.length; i += 1) {
var parameters = Object.keys(reqPart);

var param = parameters[i];
var paramKey;
var paramValue;

if (!_.isArray(req[requestPart][param])) {
continue;
}
for (var i = 0, parametersLen = parameters.length; i < parametersLen; i += 1) {

// Put aside
req[polluted][param] = req[requestPart][param];
// Select the first parameter value
req[requestPart][param] = req[requestPart][param][0];
paramKey = parameters[i];
paramValue = reqPart[paramKey];

if (!isArray(paramValue)) {
continue;
}

// Put aside
reqPolluted[paramKey] = paramValue;
// Select the first parameter value
reqPart[paramKey] = paramValue[0];

}

// Processed seperately to allow multiple whitelists from multiple HPP middlewares as well as for performance reasons
if (options.whitelist) {
}

// Processed seperately to allow multiple whitelists from multiple HPP middlewares as well as
// for performance reasons
if (isArray(whitelist)) {

for ( var k = 0; k < options.whitelist.length; k+=1 ) {
var whitelistedParam;

var whitelistedParam = options.whitelist[k];
for (var k = 0, whitelistLen = whitelist.length; k < whitelistLen; k += 1) {

if (req[polluted][whitelistedParam]) {
// Put back
req[requestPart][whitelistedParam] = req[polluted][whitelistedParam];
delete req[polluted][whitelistedParam];
}
whitelistedParam = whitelist[k];

if (reqPolluted[whitelistedParam]) {
// Put back
reqPart[whitelistedParam] = reqPolluted[whitelistedParam];
delete reqPolluted[whitelistedParam];
}

}

};
}

}

var putAsideInQuery = fnPutAsideIn('query');
var putAsideInBody = fnPutAsideIn('body');


/**
* @public
* @param {object} req
* @param {object} [req.query]
* @param {object} [req.body]
* @param {object} res
* @param {function} next
*/
return function hppMiddleware(req, res, next) {

if (options.checkQuery && req.query) {
putAsideInQuery(req);
_putAside('query', req);
}

if (options.checkBody && req.body && correctContentType(req)) {
putAsideInBody(req);
if (options.checkBody && req.body && _correctContentType(req)) {
_putAside('body', req);
}

next();

};

};