Browse Source

Merge pull request #117 from pelias/better-bbox-desc

Better way of describing bbox param
pull/124/head
Diana Shkolnikov 10 years ago
parent
commit
e5a1d12ced
  1. 3
      DOCS.md
  2. 164
      sanitiser/_geo.js
  3. 16
      test/unit/sanitiser/search.js
  4. 16
      test/unit/sanitiser/suggest.js

3
DOCS.md

@ -18,7 +18,8 @@ Full text search endpoint which queries the elasticsearch doc store, slightly sl
* can also be specific to one particular dataset, for example ```geoname```
* **bbox**: the bounding box from which you want all your results to come
* can be one of the following comma separated string values
* bottom left lat, bottom left lon, top right lat, top right lon
* "southwest_lng,southwest_lat,northeast_lng,northeast_lat" ```L.latLngBounds(southwestLatLng, northeastLatLng).toBBoxString()```
* bottom left lon, bottom left lat, top right lon, top right lat
* left, bottom, right, top
* min longitude, min latitude, max longitude, max latitude
* **details**: indicates if results should contain detailed, should be `true` or `false`

164
sanitiser/_geo.js

@ -1,10 +1,11 @@
var isObject = require('is-object');
// validate inputs, convert types and apply defaults
function sanitize( req, latlon_is_required ){
module.exports = function sanitize( req, latlon_is_required ){
var clean = req.clean || {};
var params= req.query;
var params = req.query;
latlon_is_required = latlon_is_required || false;
// ensure the input params are a valid object
@ -12,87 +13,102 @@ function sanitize( req, latlon_is_required ){
params = {};
}
var is_invalid_lat = function(lat) {
return isNaN( lat ) || lat < -90 || lat > 90;
};
var is_invalid_lon = function(lon) {
return isNaN( lon ) || lon < -180 || lon > 180;
};
// lat
var lat = parseFloat( params.lat, 10 );
if (!isNaN(lat)) {
if( is_invalid_lat(lat) ){
return {
'error': true,
'message': 'invalid param \'lat\': must be >-90 and <90'
};
}
clean.lat = lat;
} else if (latlon_is_required) {
try {
sanitize_coord( 'lat', clean, params.lat, latlon_is_required );
sanitize_coord( 'lon', clean, params.lon, latlon_is_required );
sanitize_zoom_level(clean, params.zoom);
sanitize_bbox(clean, params.bbox);
}
catch (err) {
return {
'error': true,
'message': 'missing param \'lat\': must be >-90 and <90'
'message': err.message
};
}
// lon
var lon = parseFloat( params.lon, 10 );
if (!isNaN(lon)) {
if( is_invalid_lon(lon) ){
return {
'error': true,
'message': 'invalid param \'lon\': must be >-180 and <180'
req.clean = clean;
return { 'error': false };
};
/**
* Parse and validate bbox parameter
* bbox = bottom_left lon, bottom_left lat, top_right lon, top_right lat
* bbox = left, bottom, right, top
* bbox = min Longitude, min Latitude, max Longitude, max Latitude
*
* @param {object} clean
* @param {string} param
*/
function sanitize_bbox( clean, param ) {
if( !param ) {
return;
}
var bbox = [];
var bboxArr = param.split( ',' );
if( Array.isArray( bboxArr ) && bboxArr.length === 4 ) {
bbox = bboxArr.filter( function( latlon, index ) {
latlon = parseFloat( latlon, 10 );
return !(lat_lon_checks[(index % 2 === 0 ? 'lon' : 'lat')].is_invalid( latlon ));
});
if( bbox.length === 4 ) {
clean.bbox = {
right: Math.max( bbox[0], bbox[2] ),
top: Math.max( bbox[1], bbox[3] ),
left: Math.min( bbox[0], bbox[2] ),
bottom: Math.min( bbox[1], bbox[3] )
};
} else {
throw new Error('invalid bbox');
}
clean.lon = lon;
} else if (latlon_is_required) {
return {
'error': true,
'message': 'missing param \'lon\': must be >-180 and <180'
};
}
}
// zoom level
var zoom = parseInt( params.zoom, 10 );
if( !isNaN( zoom ) ){
clean.zoom = Math.min( Math.max( zoom, 1 ), 18 ); // max
}
// bbox
// bbox = bottom_left lat, bottom_left lon, top_right lat, top_right lon
// bbox = left,bottom,right,top
// bbox = min Longitude , min Latitude , max Longitude , max Latitude
if (params.bbox) {
var bbox = [];
var bboxArr = params.bbox.split(',');
if( Array.isArray(bboxArr) && bboxArr.length === 4 ) {
bbox = bboxArr.filter(function(latlon, index) {
latlon = parseFloat(latlon, 10);
return !(index % 2 === 0 ? is_invalid_lat(latlon) : is_invalid_lon(latlon));
});
if (bbox.length === 4) {
clean.bbox = {
top : Math.max(bbox[0], bbox[2]),
right : Math.max(bbox[1], bbox[3]),
bottom: Math.min(bbox[0], bbox[2]),
left : Math.min(bbox[1], bbox[3])
};
} else {
return {
'error': true,
'message': 'invalid bbox'
};
}
/**
* Validate lat,lon values
*
* @param {string} coord lat|lon
* @param {object} clean
* @param {string} param
* @param {bool} latlon_is_required
*/
function sanitize_coord( coord, clean, param, latlon_is_required ) {
var value = parseFloat( param, 10 );
if ( !isNaN( value ) ) {
if( lat_lon_checks[coord].is_invalid( value ) ){
throw new Error( 'invalid ' + lat_lon_checks[coord].error_msg );
}
}
req.clean = clean;
return { 'error': false };
clean[coord] = value;
}
else if (latlon_is_required) {
throw new Error('missing ' + lat_lon_checks[coord].error_msg);
}
}
function sanitize_zoom_level( clean, param ) {
var zoom = parseInt( param, 10 );
if( !isNaN( zoom ) ){
clean.zoom = Math.min( Math.max( zoom, 1 ), 18 ); // max
}
}
// export function
module.exports = sanitize;
var lat_lon_checks = {
lat: {
is_invalid: function is_invalid_lat(lat) {
return isNaN( lat ) || lat < -90 || lat > 90;
},
error_msg: 'param \'lat\': must be >-90 and <90'
},
lon: {
is_invalid: function is_invalid_lon(lon) {
return isNaN(lon) || lon < -180 || lon > 180;
},
error_msg: 'param \'lon\': must be >-180 and <180'
}
};

16
test/unit/sanitiser/search.js

@ -168,9 +168,9 @@ module.exports.tests.sanitize_optional_geo = function(test, common) {
module.exports.tests.sanitize_bbox = function(test, common) {
var bboxes = {
invalid_coordinates: [
'90,-181,-180,34', // invalid top_right lon, bottom_left lat
'91,-170,45,-181', // invalid top_right lat, bottom_left lon
'91,-181,-91,181', // invalid top_right lat/lon, bottom_left lat/lon
'-181,90,34,-180', // invalid top_right lon, bottom_left lat
'-170,91,-181,45', // invalid top_right lat, bottom_left lon
'-181,91,181,-91', // invalid top_right lon/lat, bottom_left lon/lat
'91, -181,-91,181',// invalid - spaces between coordinates
],
invalid: [
@ -180,7 +180,7 @@ module.exports.tests.sanitize_bbox = function(test, common) {
'' // invalid - empty param
],
valid: [
'90,-179,-80,34', // valid top_right lat/lon, bottom_left lat/lon
'-179,90,34,-80', // valid top_right lon/lat, bottom_left lon/lat
'0,0,0,0' // valid top_right lat/lon, bottom_left lat/lon
]
@ -212,10 +212,10 @@ module.exports.tests.sanitize_bbox = function(test, common) {
return parseInt(i);
});
expected.bbox = {
top : Math.max(bboxArray[0], bboxArray[2]),
right : Math.max(bboxArray[1], bboxArray[3]),
bottom: Math.min(bboxArray[0], bboxArray[2]),
left : Math.min(bboxArray[1], bboxArray[3])
right: Math.max(bboxArray[0], bboxArray[2]),
top: Math.max(bboxArray[1], bboxArray[3]),
left: Math.min(bboxArray[0], bboxArray[2]),
bottom: Math.min(bboxArray[1], bboxArray[3])
};
t.equal(err, undefined, 'no error');
t.deepEqual(clean, expected, 'clean set correctly (' + bbox + ')');

16
test/unit/sanitiser/suggest.js

@ -137,9 +137,9 @@ module.exports.tests.sanitize_lon = function(test, common) {
module.exports.tests.sanitize_bbox = function(test, common) {
var bboxes = {
invalid_coordinates: [
'90,-181,-180,34', // invalid top_right lon, bottom_left lat
'91,-170,45,-181', // invalid top_right lat, bottom_left lon
'91,-181,-91,181', // invalid top_right lat/lon, bottom_left lat/lon
'-181,90,34,-180', // invalid top_right lon, bottom_left lat
'-170,91,-181,45', // invalid top_right lat, bottom_left lon
'-181,91,181,-91', // invalid top_right lon/lat, bottom_left lon/lat
'91, -181,-91,181',// invalid - spaces between coordinates
],
invalid: [
@ -149,7 +149,7 @@ module.exports.tests.sanitize_bbox = function(test, common) {
'' // invalid - empty param
],
valid: [
'90,-179,-80,34', // valid top_right lat/lon, bottom_left lat/lon
'-179,90,34,-80', // valid top_right lon/lat, bottom_left lon/lat
'0,0,0,0' // valid top_right lat/lon, bottom_left lat/lon
]
@ -181,10 +181,10 @@ module.exports.tests.sanitize_bbox = function(test, common) {
return parseInt(i);
});
expected.bbox = {
top : Math.max(bboxArray[0], bboxArray[2]),
right : Math.max(bboxArray[1], bboxArray[3]),
bottom: Math.min(bboxArray[0], bboxArray[2]),
left : Math.min(bboxArray[1], bboxArray[3])
right: Math.max(bboxArray[0], bboxArray[2]),
top: Math.max(bboxArray[1], bboxArray[3]),
left: Math.min(bboxArray[0], bboxArray[2]),
bottom: Math.min(bboxArray[1], bboxArray[3])
};
t.equal(err, undefined, 'no error');
t.deepEqual(clean, expected, 'clean set correctly (' + bbox + ')');

Loading…
Cancel
Save