From 11673cfa86515edcefa260085e194179d015a4bf Mon Sep 17 00:00:00 2001 From: Stephen Hess Date: Tue, 19 Sep 2017 14:45:09 -0400 Subject: [PATCH] add support for passing sanitized layers to wof-admin-lookup --- app.js | 31 ++++++++++++- test/app.js | 126 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 155 insertions(+), 2 deletions(-) diff --git a/app.js b/app.js index 759ca01..08fd0be 100644 --- a/app.js +++ b/app.js @@ -28,11 +28,38 @@ const validate = (req, res, next) => { } + +}; + +// middleware that cleans up layers parameters, eg: +// 'layers=layer1,layer2' => ['layer1', 'layer2'] +// 'layers= layer1 , , layer2 ' => ['layer1', 'layer2'] +// 'layers= , , ' => undefined +// 'layers=' => undefined +// no layers parameter => undefined +const parseLayers = (req, res, next) => { + const layers = _.split(req.query.layers, ',').reduce((layers, layer) => { + // only add to the valid layers list if it's not reduceable to an empty string + if (!_.isEmpty(_.trim(layer))) { + layers.push(_.trim(layer)); + } + return layers; + }, []); + + // if there are no layers, remove the parameter + if (_.isEmpty(layers)) { + delete req.query.layers; + } else { + req.query.layers = layers; + } + + next(); + }; function lookup(pointInPoly) { return (req, res, next) => { - pointInPoly.lookup(req.query.centroid, undefined, (err, result) => { + pointInPoly.lookup(req.query.centroid, req.query.layers, (err, result) => { req.query.resolved = result; next(); }); @@ -73,7 +100,7 @@ module.exports = (datapath) => { const pointInPoly = adminLookup.resolver(datapath); const router = new Router(); - router.get('/:lon/:lat', validate, lookup(pointInPoly), output); + router.get('/:lon/:lat', validate, parseLayers, lookup(pointInPoly), output); app.use(log(), router); return app; diff --git a/test/app.js b/test/app.js index 6d410ad..e90786b 100644 --- a/test/app.js +++ b/test/app.js @@ -49,6 +49,132 @@ tape('entry point tests', (test) => { }); + test.test('layers should be passed to lookup when supplied', t => { + const logger = mocklogger(); + + temp.mkdir('whosonfirst', (err, temp_dir) => { + t.notOk(err); + + fs.mkdirSync(path.join(temp_dir, 'data')); + fs.mkdirSync(path.join(temp_dir, 'meta')); + + const app = proxyquire('../app', { + 'pelias-wof-admin-lookup': { + resolver: (datapath) => { + t.equals(datapath, temp_dir); + return { + lookup: (centroid, layers, callback) => { + t.deepEquals(centroid, { lat: 12.121212, lon: 21.212121 }); + t.deepEquals(layers, ['layer1', 'layer2']); + callback(undefined, 'this is the result'); + } + }; + } + }, + 'pelias-logger': logger + })(temp_dir); + const server = app.listen(); + const port = server.address().port; + + request.get(`http://localhost:${port}/21.212121/12.121212?layers=%20layer1%20,,%20layer2%20`, (err, response, body) => { + t.ok(logger.isInfoMessage(/GET \/21.212121\/12.121212\?layers=%20layer1%20,,%20layer2%20 /)); + t.notOk(err); + t.equals(response.statusCode, 200); + t.equals(body, 'this is the result'); + t.end(); + server.close(); + temp.cleanupSync(); + + }); + + }); + + }); + + test.test('layers trimmable to empty string should pass undefined to lookup', t => { + const logger = mocklogger(); + + temp.mkdir('whosonfirst', (err, temp_dir) => { + t.notOk(err); + + fs.mkdirSync(path.join(temp_dir, 'data')); + fs.mkdirSync(path.join(temp_dir, 'meta')); + + const app = proxyquire('../app', { + 'pelias-wof-admin-lookup': { + resolver: (datapath) => { + t.equals(datapath, temp_dir); + return { + lookup: (centroid, layers, callback) => { + t.deepEquals(centroid, { lat: 12.121212, lon: 21.212121 }); + t.deepEquals(layers, undefined); + callback(undefined, 'this is the result'); + } + }; + } + }, + 'pelias-logger': logger + })(temp_dir); + const server = app.listen(); + const port = server.address().port; + + request.get(`http://localhost:${port}/21.212121/12.121212?layers=%20`, (err, response, body) => { + t.ok(logger.isInfoMessage(/GET \/21.212121\/12.121212\?layers=%20 /)); + t.notOk(err); + t.equals(response.statusCode, 200); + t.equals(body, 'this is the result'); + t.end(); + server.close(); + temp.cleanupSync(); + + }); + + }); + + }); + + test.test('layers reduceable to all empty strings should pass undefined to lookup', t => { + const logger = mocklogger(); + + temp.mkdir('whosonfirst', (err, temp_dir) => { + t.notOk(err); + + fs.mkdirSync(path.join(temp_dir, 'data')); + fs.mkdirSync(path.join(temp_dir, 'meta')); + + const app = proxyquire('../app', { + 'pelias-wof-admin-lookup': { + resolver: (datapath) => { + t.equals(datapath, temp_dir); + return { + lookup: (centroid, layers, callback) => { + t.deepEquals(centroid, { lat: 12.121212, lon: 21.212121 }); + t.deepEquals(layers, undefined); + callback(undefined, 'this is the result'); + } + }; + } + }, + 'pelias-logger': logger + })(temp_dir); + const server = app.listen(); + const port = server.address().port; + + request.get(`http://localhost:${port}/21.212121/12.121212?layers=,,`, (err, response, body) => { + t.ok(logger.isInfoMessage(/GET \/21.212121\/12.121212\?layers=,, /)); + t.notOk(err); + t.equals(response.statusCode, 200); + t.equals(body, 'this is the result'); + t.end(); + server.close(); + temp.cleanupSync(); + + }); + + }); + + }); + test.test('request not matching desired path should return 404', (t) => { const logger = mocklogger();