Browse Source

split sanitizers into reusable pieces. renaming sanitise to suggest. using suggest sanitizer for search. adding reverse sanitizer. updating tests..

pull/5/head
Harish Krishna 10 years ago
parent
commit
32275aca56
  1. 10
      app.js
  2. 26
      sanitiser/_input.js
  3. 47
      sanitiser/_latlonzoom.js
  4. 40
      sanitiser/_layers.js
  5. 17
      sanitiser/_sanitize.js
  6. 27
      sanitiser/_size.js
  7. 23
      sanitiser/reverse.js
  8. 84
      sanitiser/sanitise.js
  9. 26
      sanitiser/suggest.js
  10. 15
      test/unit/sanitiser/sanitise.js

10
app.js

@ -14,7 +14,9 @@ middlewares.search = require('./middleware/search');
/** ----------------------- sanitisers ----------------------- **/
var sanitisers = {};
sanitisers.sanitiser= require('./sanitiser/sanitise');
sanitisers.suggest = require('./sanitiser/suggest');
sanitisers.search = sanitisers.suggest;
sanitisers.reverse = require('./sanitiser/reverse');
/** ----------------------- controllers ----------------------- **/
@ -29,13 +31,13 @@ controllers.search = require('./controller/search');
app.get( '/', controllers.index() );
// suggest API
app.get( '/suggest', sanitisers.sanitiser.middleware, controllers.suggest() );
app.get( '/suggest', sanitisers.suggest.middleware, controllers.suggest() );
// search API
app.get( '/search', sanitisers.sanitiser.middleware, middlewares.search.middleware, controllers.search() );
app.get( '/search', sanitisers.search.middleware, middlewares.search.middleware, controllers.search() );
// reverse API
app.get( '/reverse', sanitisers.sanitiser.middleware, controllers.search(undefined, require('query/reverse')) );
app.get( '/reverse', sanitisers.reverse.middleware, controllers.search(undefined, require('query/reverse')) );
/** ----------------------- error middleware ----------------------- **/

26
sanitiser/_input.js

@ -0,0 +1,26 @@
// validate inputs, convert types and apply defaults
function sanitize( req ){
req.clean = req.clean || {};
var params= req.query;
// ensure the input params are a valid object
if( Object.prototype.toString.call( params ) !== '[object Object]' ){
params = {};
}
// input text
if('string' !== typeof params.input || !params.input.length){
return {
'error': true,
'message': 'invalid param \'input\': text length, must be >0'
};
}
req.clean.input = params.input;
return { 'error': false };
}
// export function
module.exports = sanitize;

47
sanitiser/_latlonzoom.js

@ -0,0 +1,47 @@
// validate inputs, convert types and apply defaults
function sanitize( req ){
var clean = req.clean || {};
var params= req.query;
// ensure the input params are a valid object
if( Object.prototype.toString.call( params ) !== '[object Object]' ){
params = {};
}
// lat
var lat = parseFloat( params.lat, 10 );
if( isNaN( lat ) || lat < 0 || lat > 90 ){
return {
'error': true,
'message': 'invalid param \'lat\': must be >0 and <90'
}
}
clean.lat = lat;
// lon
var lon = parseFloat( params.lon, 10 );
if( isNaN( lon ) || lon < -180 || lon > 180 ){
return {
'error': true,
'message': 'invalid param \'lon\': must be >-180 and <180'
}
}
clean.lon = lon;
// zoom level
var zoom = parseInt( params.zoom, 10 );
if( !isNaN( zoom ) ){
clean.zoom = Math.min( Math.max( zoom, 1 ), 18 ); // max
} else {
clean.zoom = 10; // default
}
req.clean = clean;
return { 'error': false };
}
// export function
module.exports = sanitize;

40
sanitiser/_layers.js

@ -0,0 +1,40 @@
var indeces = require('../query/indeces');
// validate inputs, convert types and apply defaults
function sanitize( req ){
var clean = req.clean || {};
var params= req.query;
// ensure the input params are a valid object
if( Object.prototype.toString.call( params ) !== '[object Object]' ){
params = {};
}
// which layers to query
if('string' === typeof params.layers && params.layers.length){
var layers = params.layers.split(',').map( function( layer ){
return layer.toLowerCase(); // lowercase inputs
});
for( var x=0; x<layers.length; x++ ){
if( -1 === indeces.indexOf( layers[x] ) ){
return {
'error': true,
'message': 'invalid param \'layer\': must be one or more of ' + indeces.join(',')
}
}
}
clean.layers = layers;
}
else {
clean.layers = indeces; // default (all layers)
}
req.clean = clean;
return { 'error': false };
}
// export function
module.exports = sanitize;

17
sanitiser/_sanitize.js

@ -0,0 +1,17 @@
function sanitize( req, sanitiser, cb ){
req.clean = req.clean || {};
for (var s in sanitiser) {
var sanity = sanitiser[s](req);
if (sanity.error) {
return cb(sanity.message);
}
}
return cb( undefined, req.clean );
}
// export function
module.exports = sanitize;

27
sanitiser/_size.js

@ -0,0 +1,27 @@
// validate inputs, convert types and apply defaults
function sanitize( req ){
var clean = req.clean || {};
var params= req.query;
// ensure the input params are a valid object
if( Object.prototype.toString.call( params ) !== '[object Object]' ){
params = {};
}
// total results
var size = parseInt( params.size, 10 );
if( !isNaN( size ) ){
clean.size = Math.min( Math.max( size, 1 ), 40 ); // max
} else {
clean.size = 10; // default
}
req.clean = clean;
return {'error':false};
}
// export function
module.exports = sanitize;

23
sanitiser/reverse.js

@ -0,0 +1,23 @@
var logger = require('../src/logger'),
_sanitize = require('../sanitiser/_sanitize'),
sanitiser = {
latlonzoom: require('../sanitiser/_latlonzoom')
};
var sanitize = function(req, cb) { _sanitize(req, sanitiser, cb); }
// export sanitize for testing
module.exports.sanitize = sanitize;
// middleware
module.exports.middleware = function( req, res, next ){
sanitize( req, function( err, clean ){
if( err ){
res.status(400); // 400 Bad Request
return next(err);
}
req.clean = clean;
next();
});
};

84
sanitiser/sanitise.js

@ -1,84 +0,0 @@
var logger = require('../src/logger'),
indeces = require('../query/indeces');
// validate inputs, convert types and apply defaults
function sanitize( params, cb ){
var clean = {};
// ensure the input params are a valid object
if( Object.prototype.toString.call( params ) !== '[object Object]' ){
params = {};
}
// input text
if('string' !== typeof params.input || !params.input.length){
return cb( 'invalid param \'input\': text length, must be >0' );
}
clean.input = params.input;
// total results
var size = parseInt( params.size, 10 );
if( !isNaN( size ) ){
clean.size = Math.min( Math.max( size, 1 ), 40 ); // max
} else {
clean.size = 10; // default
}
// which layers to query
if('string' === typeof params.layers && params.layers.length){
var layers = params.layers.split(',').map( function( layer ){
return layer.toLowerCase(); // lowercase inputs
});
for( var x=0; x<layers.length; x++ ){
if( -1 === indeces.indexOf( layers[x] ) ){
return cb( 'invalid param \'layer\': must be one or more of ' + indeces.join(',') );
}
}
clean.layers = layers;
}
else {
clean.layers = indeces; // default (all layers)
}
// lat
var lat = parseFloat( params.lat, 10 );
if( isNaN( lat ) || lat < 0 || lat > 90 ){
return cb( 'invalid param \'lat\': must be >0 and <90' );
}
clean.lat = lat;
// lon
var lon = parseFloat( params.lon, 10 );
if( isNaN( lon ) || lon < -180 || lon > 180 ){
return cb( 'invalid param \'lon\': must be >-180 and <180' );
}
clean.lon = lon;
// zoom level
var zoom = parseInt( params.zoom, 10 );
if( !isNaN( zoom ) ){
clean.zoom = Math.min( Math.max( zoom, 1 ), 18 ); // max
} else {
clean.zoom = 10; // default
}
return cb( undefined, clean );
}
// export function
module.exports = sanitize;
// middleware
module.exports.middleware = function( req, res, next ){
sanitize( req.query, function( err, clean ){
if( err ){
res.status(400); // 400 Bad Request
return next(err);
}
req.clean = clean;
next();
});
};

26
sanitiser/suggest.js

@ -0,0 +1,26 @@
var logger = require('../src/logger'),
_sanitize = require('../sanitiser/_sanitize'),
sanitizers = {
input: require('../sanitiser/_input'),
size: require('../sanitiser/_size'),
layers: require('../sanitiser/_layers'),
latlonzoom: require('../sanitiser/_latlonzoom')
};
var sanitize = function(req, cb) { _sanitize(req, sanitizers, cb); }
// export sanitize for testing
module.exports.sanitize = sanitize;
// middleware
module.exports.middleware = function( req, res, next ){
sanitize( req, function( err, clean ){
if( err ){
res.status(400); // 400 Bad Request
return next(err);
}
req.clean = clean;
next();
});
};

15
test/unit/sanitiser/sanitise.js

@ -1,7 +1,10 @@
var sanitize = require('../../../sanitiser/sanitise'),
var suggest = require('../../../sanitiser/suggest'),
_sanitize = suggest.sanitize,
middleware = suggest.middleware,
defaultError = 'invalid param \'input\': text length, must be >0',
defaultClean = { input: 'test', lat: 0, layers: [ 'geoname', 'osmnode', 'osmway', 'admin0', 'admin1', 'admin2', 'neighborhood' ], lon: 0, size: 10, zoom: 10 };
defaultClean = { input: 'test', lat: 0, layers: [ 'geoname', 'osmnode', 'osmway', 'admin0', 'admin1', 'admin2', 'neighborhood' ], lon: 0, size: 10, zoom: 10 },
sanitize = function(query, cb) { _sanitize({'query':query}, cb); }
module.exports.tests = {};
@ -12,8 +15,8 @@ module.exports.tests.interface = function(test, common) {
t.end();
});
test('middleware interface', function(t) {
t.equal(typeof sanitize.middleware, 'function', 'middleware is a function');
t.equal(sanitize.middleware.length, 3, 'sanitize is valid middleware');
t.equal(typeof middleware, 'function', 'middleware is a function');
t.equal(middleware.length, 3, 'sanitizee has a valid middleware');
t.end();
});
};
@ -175,7 +178,7 @@ module.exports.tests.middleware_failure = function(test, common) {
t.equal(message, defaultError);
t.end();
};
sanitize.middleware( {}, res, next );
middleware( {}, res, next );
});
};
@ -187,7 +190,7 @@ module.exports.tests.middleware_success = function(test, common) {
t.deepEqual(req.clean, defaultClean);
t.end();
};
sanitize.middleware( req, undefined, next );
middleware( req, undefined, next );
});
};

Loading…
Cancel
Save