diff --git a/package.json b/package.json index 19f3f83e..6fc414c5 100644 --- a/package.json +++ b/package.json @@ -60,8 +60,7 @@ "pelias-config": "2.10.0", "pelias-labels": "1.6.0", "pelias-logger": "0.2.0", - "pelias-mock-logger": "^1.0.1", - "pelias-model": "4.8.1", + "pelias-microservice-wrapper": "^1.1.0", "pelias-query": "8.15.0", "pelias-text-analyzer": "1.8.2", "predicates": "^1.0.1", @@ -78,6 +77,7 @@ "jshint": "^2.5.6", "npm-check": "git://github.com/orangejulius/npm-check.git#disable-update-check", "nsp": "^2.2.0", + "pelias-mock-logger": "^1.0.1", "precommit-hook": "^3.0.0", "proxyquire": "^1.7.10", "semantic-release": "^6.3.2", diff --git a/routes/v1.js b/routes/v1.js index 7b5d8e3a..e66d73d5 100644 --- a/routes/v1.js +++ b/routes/v1.js @@ -4,6 +4,7 @@ var elasticsearch = require('elasticsearch'); const all = require('predicates').all; const any = require('predicates').any; const not = require('predicates').not; +const _ = require('lodash'); /** ----------------------- sanitizers ----------------------- **/ var sanitizers = { @@ -72,6 +73,7 @@ const isAdminOnlyAnalysis = require('../controller/predicates/is_admin_only_anal // shorthand for standard early-exit conditions const hasResponseDataOrRequestErrors = any(hasResponseData, hasRequestErrors); +const serviceWrapper = require('pelias-microservice-wrapper').service; const PlaceHolder = require('../service/configurations/PlaceHolder'); /** @@ -88,8 +90,8 @@ function addRoutes(app, peliasConfig) { const pipService = require('../service/pointinpolygon')(peliasConfig.api.pipService); const placeholderConfiguration = new PlaceHolder(peliasConfig.api.services.placeholder); - const placeholderService = require('../service/http_json')(placeholderConfiguration); - const isPlaceholderServiceEnabled = require('../controller/predicates/is_service_enabled')(placeholderConfiguration.getBaseUrl()); + const placeholderService = serviceWrapper(placeholderConfiguration); + const isPlaceholderServiceEnabled = _.constant(placeholderConfiguration.isEnabled()); const coarse_reverse_should_execute = all( not(hasRequestErrors), isPipServiceEnabled, isCoarseReverse diff --git a/service/configurations/PlaceHolder.js b/service/configurations/PlaceHolder.js index 5f7fb464..9102184d 100644 --- a/service/configurations/PlaceHolder.js +++ b/service/configurations/PlaceHolder.js @@ -1,8 +1,10 @@ 'use strict'; +const url = require('url'); + const _ = require('lodash'); -const ServiceConfiguration = require('./ServiceConfiguration'); +const ServiceConfiguration = require('pelias-microservice-wrapper').ServiceConfiguration; class PlaceHolder extends ServiceConfiguration { constructor(o) { @@ -22,7 +24,7 @@ class PlaceHolder extends ServiceConfiguration { } getUrl(req) { - return `${this.baseUrl}/search`; + return url.resolve(this.baseUrl, 'search'); } } diff --git a/service/configurations/ServiceConfiguration.js b/service/configurations/ServiceConfiguration.js deleted file mode 100644 index 3fe0d75f..00000000 --- a/service/configurations/ServiceConfiguration.js +++ /dev/null @@ -1,48 +0,0 @@ -'use strict'; - -const _ = require('lodash'); - -class ServiceConfiguration { - constructor(name, config) { - if (_.isEmpty(name)) { - throw 'name is required'; - } - - this.name = name; - this.baseUrl = config.url; - this.timeout = config.timeout || 250; - this.retries = config.retries || 3; - - } - - getName() { - return this.name; - } - - getBaseUrl() { - return this.baseUrl; - } - - getUrl() { - return this.baseUrl; - } - - getRetries() { - return this.retries; - } - - getTimeout() { - return this.timeout; - } - - getParameters() { - return {}; - } - - getHeaders() { - return {}; - } - -} - -module.exports = ServiceConfiguration; diff --git a/service/http_json.js b/service/http_json.js deleted file mode 100644 index 67b0252f..00000000 --- a/service/http_json.js +++ /dev/null @@ -1,100 +0,0 @@ -const request = require('superagent'); -const _ = require('lodash'); -const isDNT = require( '../helper/logging' ).isDNT; - -const logger = require( 'pelias-logger' ).get( 'placeholder' ); - -const ServiceConfiguration = require('./configurations/ServiceConfiguration'); - -// superagent doesn't exposed the assembled GET request, so synthesize it -function synthesizeUrl(serviceConfig, req) { - const parameters = _.map(serviceConfig.getParameters(), (value, key) => { - return `${key}=${value}`; - }).join('&'); - - if (parameters) { - return encodeURI(`${serviceConfig.getUrl(req)}?${parameters}`); - } else { - return serviceConfig.getUrl(req); - } - -} - -module.exports = function setup(serviceConfig) { - if (!(serviceConfig instanceof ServiceConfiguration)) { - throw Error('serviceConfig should be an instance of ServiceConfiguration'); - } - - if (_.isEmpty(serviceConfig.getBaseUrl())) { - logger.warn(`${serviceConfig.getName()} service disabled`); - - return (req, callback) => { - // respond with an error to any call - callback(`${serviceConfig.getName()} service disabled`); - }; - - } - - logger.info(`using ${serviceConfig.getName()} service at ${serviceConfig.getBaseUrl()}`); - return (req, callback) => { - const headers = serviceConfig.getHeaders(req) || {}; - const do_not_track = isDNT(req); - - if (do_not_track) { - headers.dnt = '1'; - } - - request - .get(serviceConfig.getUrl(req)) - .set(headers) - .timeout(serviceConfig.getTimeout()) - .retry(serviceConfig.getRetries()) - .accept('json') - .query(serviceConfig.getParameters(req)) - .on('error', (err) => { - if (err.status) { - // first handle case where a non-200 was returned - if (do_not_track) { - logger.error(`${serviceConfig.getBaseUrl()} [do_not_track] returned status ${err.status}: ${err.response.text}`); - return callback(`${serviceConfig.getBaseUrl()} [do_not_track] returned status ${err.status}: ${err.response.text}`); - } else { - logger.error(`${synthesizeUrl(serviceConfig, req)} returned status ${err.status}: ${err.response.text}`); - return callback(`${synthesizeUrl(serviceConfig, req)} returned status ${err.status}: ${err.response.text}`); - } - - } - - // handle case that something catastrophic happened while contacting the server - if (do_not_track) { - logger.error(`${serviceConfig.getBaseUrl()} [do_not_track]: ${JSON.stringify(err)}`); - return callback(err); - } else { - logger.error(`${serviceConfig.getUrl(req)}: ${JSON.stringify(err)}`); - return callback(err); - } - - }) - .end((err, response) => { - // bail early if there's an error (shouldn't happen since it was already handled above) - if (err) { - return; - } - - // if json was returned then just return it - if (response.type === 'application/json') { - return callback(null, response.body); - } - - if (do_not_track) { - logger.error(`${serviceConfig.getBaseUrl()} [do_not_track] could not parse response: ${response.text}`); - return callback(`${serviceConfig.getBaseUrl()} [do_not_track] could not parse response: ${response.text}`); - } else { - logger.error(`${synthesizeUrl(serviceConfig, req)} could not parse response: ${response.text}`); - return callback(`${synthesizeUrl(serviceConfig, req)} could not parse response: ${response.text}`); - } - - }); - - }; - -}; diff --git a/test/unit/run.js b/test/unit/run.js index 7bb2adc7..5f5776d8 100644 --- a/test/unit/run.js +++ b/test/unit/run.js @@ -80,9 +80,7 @@ var tests = [ require('./sanitizer/search'), require('./sanitizer/search_fallback'), require('./sanitizer/wrap'), - require('./service/http_json'), require('./service/configurations/PlaceHolder'), - require('./service/configurations/ServiceConfiguration'), require('./service/mget'), require('./service/search'), require('./service/interpolation'), diff --git a/test/unit/service/configurations/PlaceHolder.js b/test/unit/service/configurations/PlaceHolder.js index 055f6318..e08ef091 100644 --- a/test/unit/service/configurations/PlaceHolder.js +++ b/test/unit/service/configurations/PlaceHolder.js @@ -5,7 +5,7 @@ const PlaceHolder = require('../../../../service/configurations/PlaceHolder'); module.exports.tests.all = (test, common) => { test('getName should return \'placeholder\'', (t) => { const configBlob = { - url: 'base url', + url: 'http://localhost:1234', timeout: 17, retries: 19 }; @@ -13,7 +13,7 @@ module.exports.tests.all = (test, common) => { const placeholder = new PlaceHolder(configBlob); t.equals(placeholder.getName(), 'placeholder'); - t.equals(placeholder.getBaseUrl(), 'base url'); + t.equals(placeholder.getBaseUrl(), 'http://localhost:1234/'); t.equals(placeholder.getTimeout(), 17); t.equals(placeholder.getRetries(), 19); t.end(); @@ -22,21 +22,21 @@ module.exports.tests.all = (test, common) => { test('getUrl should return value passed to constructor', (t) => { const configBlob = { - url: 'base url', + url: 'http://localhost:1234', timeout: 17, retries: 19 }; const placeholder = new PlaceHolder(configBlob); - t.equals(placeholder.getUrl(), 'base url/search'); + t.equals(placeholder.getUrl(), 'http://localhost:1234/search'); t.end(); }); test('getParameters should return object with text and lang from req', (t) => { const configBlob = { - url: 'base url', + url: 'http://localhost:1234', timeout: 17, retries: 19 }; @@ -112,6 +112,20 @@ module.exports.tests.all = (test, common) => { }); + test('baseUrl ending in / should not have double /\'s return by getUrl', (t) => { + const configBlob = { + url: 'http://localhost:1234/blah', + timeout: 17, + retries: 19 + }; + + const placeholder = new PlaceHolder(configBlob); + + t.deepEquals(placeholder.getUrl(), 'http://localhost:1234/blah/search'); + t.end(); + + }); + }; module.exports.all = (tape, common) => { diff --git a/test/unit/service/configurations/ServiceConfiguration.js b/test/unit/service/configurations/ServiceConfiguration.js deleted file mode 100644 index ca31b327..00000000 --- a/test/unit/service/configurations/ServiceConfiguration.js +++ /dev/null @@ -1,58 +0,0 @@ -module.exports.tests = {}; - -const ServiceConfiguration = require('../../../../service/configurations/ServiceConfiguration'); - -module.exports.tests.all = (test, common) => { - test('timeout and retries overrides should be returned by getters', (t) => { - const configBlob = { - url: 'base url', - timeout: 17, - retries: 19 - }; - - const serviceConfiguration = new ServiceConfiguration('service name', configBlob); - - t.equals(serviceConfiguration.getName(), 'service name'); - t.equals(serviceConfiguration.getBaseUrl(), 'base url'); - t.deepEquals(serviceConfiguration.getParameters(), {}); - t.deepEquals(serviceConfiguration.getHeaders(), {}); - t.equals(serviceConfiguration.getUrl(), 'base url'); - t.equals(serviceConfiguration.getRetries(), 19); - t.equals(serviceConfiguration.getTimeout(), 17); - t.end(); - - }); - - test('configBlob w/o timeout or retries should default to 250 and 3, respectively', (t) => { - const configBlob = { - url: 'base url' - }; - - const serviceConfiguration = new ServiceConfiguration('service name', configBlob); - - t.equals(serviceConfiguration.getTimeout(), 250, 'should be a default of 250'); - t.equals(serviceConfiguration.getRetries(), 3, 'should be a default of 3'); - t.end(); - - }); - - test('missing name should throw error', (t) => { - t.throws(() => { - // lint complains if using `new` and not assigning to something - const config = new ServiceConfiguration(undefined, { url: 'base url' }); - }, /^name is required$/); - t.end(); - - }); - -}; - -module.exports.all = (tape, common) => { - function test(name, testFunction) { - return tape(`SERVICE CONFIGURATION /ServiceConfiguration ${name}`, testFunction); - } - - for( var testCase in module.exports.tests ){ - module.exports.tests[testCase](test, common); - } -}; diff --git a/test/unit/service/http_json.js b/test/unit/service/http_json.js deleted file mode 100644 index 7bb1d7a9..00000000 --- a/test/unit/service/http_json.js +++ /dev/null @@ -1,569 +0,0 @@ -'use strict'; - -const proxyquire = require('proxyquire').noCallThru(); -const express = require('express'); - -const setup = require('../../../service/http_json'); -const ServiceConfiguration = require('../../../service/configurations/ServiceConfiguration'); - -module.exports.tests = {}; - -module.exports.tests.interface = (test, common) => { - test('valid interface', (t) => { - const logger = require('pelias-mock-logger')(); - - var service = proxyquire('../../../service/http_json', { - 'pelias-logger': logger - }); - - t.equal(typeof service, 'function', 'service is a function'); - t.end(); - }); -}; - -module.exports.tests.conforms_to = (test, common) => { - test('non-ServiceConfiguration instance should throw error', (t) => { - const serviceConfig = 'not an instance of serviceConfiguration'; - - t.throws(setup.bind(null, serviceConfig), /serviceConfig should be an instance of ServiceConfiguration/); - t.end(); - - }); - -}; - -module.exports.tests.do_nothing_service = (test, common) => { - test('undefined config.url should return service that logs that config.name service is not available', (t) => { - const logger = require('pelias-mock-logger')(); - - const MockServiceConfig = class extends ServiceConfiguration { - constructor(o) { - super('foo', { } ); - } - }; - - const service = proxyquire('../../../service/http_json', { - 'pelias-logger': logger - })(new MockServiceConfig()); - - t.ok(logger.isWarnMessage(/^foo service disabled$/)); - - service({}, (err) => { - t.equals(err, 'foo service disabled'); - t.end(); - }); - - }); - -}; - -module.exports.tests.failure_conditions = (test, common) => { - test('server returning error should log it and return no results', (t) => { - const server = express().listen(); - const port = server.address().port; - - // immediately close the server so to ensure an error response - server.close(); - - const logger = require('pelias-mock-logger')(); - - const MockServiceConfig = class extends ServiceConfiguration { - constructor(o) { - super('foo', { url: `http://localhost:${port}` } ); - } - getUrl(req) { - return `http://localhost:${port}/built_url`; - } - }; - - const service = proxyquire('../../../service/http_json', { - 'pelias-logger': logger - })(new MockServiceConfig()); - - t.ok(logger.isInfoMessage(new RegExp(`using foo service at http://localhost:${port}`))); - - service({}, (err, results) => { - t.equals(err.code, 'ECONNREFUSED'); - t.notOk(results); - t.ok(logger.isErrorMessage(new RegExp(`^http://localhost:${port}/built_url: .*ECONNREFUSED`)), - 'there should be a connection refused error message'); - t.end(); - - server.close(); - - }); - - }); - - test('[DNT] server returning error should log it w/sanitized URL and return no results', (t) => { - const server = express().listen(); - const port = server.address().port; - - // immediately close the server so to ensure an error response - server.close(); - - const logger = require('pelias-mock-logger')(); - - const MockServiceConfig = class extends ServiceConfiguration { - constructor(o) { - super('foo', { url: `http://localhost:${port}` } ); - } - getUrl(req) { - return `http://localhost:${port}/built_url`; - } - }; - - const service = proxyquire('../../../service/http_json', { - 'pelias-logger': logger, - '../helper/logging': { - isDNT: () => { return true; } - } - })(new MockServiceConfig()); - - t.ok(logger.isInfoMessage(new RegExp(`using foo service at http://localhost:${port}`))); - - service({}, (err, results) => { - t.equals(err.code, 'ECONNREFUSED'); - t.notOk(results); - t.ok(logger.isErrorMessage(new RegExp(`^http://localhost:${port} \\[do_not_track\\]: .*ECONNREFUSED`)), - 'there should be a connection refused error message'); - t.end(); - - server.close(); - - }); - - }); - - test('server returning non-200 response should log error and return no results', (t) => { - const webServer = express(); - webServer.get('/some_endpoint', (req, res, next) => { - t.notOk(req.headers.hasOwnProperty('dnt'), 'dnt header should not have been passed'); - - t.equals(req.headers.header1, 'header1 value', 'all headers should have been passed'); - t.deepEquals(req.query, { param1: 'param1 value', param2: 'param2 value' }); - - res.status(400).send('a bad request was made'); - }); - - const server = webServer.listen(); - const port = server.address().port; - - const logger = require('pelias-mock-logger')(); - - const MockServiceConfig = class extends ServiceConfiguration { - constructor(o) { - super('foo', { url: `http://localhost:${port}` } ); - } - getUrl(req) { - return `http://localhost:${port}/some_endpoint`; - } - getParameters(req) { - return { param1: 'param1 value', param2: 'param2 value' }; - } - getHeaders(req) { - return { header1: 'header1 value' }; - } - }; - - const service = proxyquire('../../../service/http_json', { - 'pelias-logger': logger - })(new MockServiceConfig()); - - t.ok(logger.isInfoMessage(new RegExp(`using foo service at http://localhost:${port}`))); - - service({}, (err, results) => { - t.equals(err, `http://localhost:${port}/some_endpoint?param1=param1%20value¶m2=param2%20value ` + - 'returned status 400: a bad request was made'); - t.notOk(results); - t.ok(logger.isErrorMessage(`http://localhost:${port}/some_endpoint?param1=param1%20value¶m2=param2%20value ` + - `returned status 400: a bad request was made`)); - t.end(); - - server.close(); - - }); - - }); - - test('[DNT] server returning non-200 response should log sanitized error and return no results', (t) => { - const webServer = express(); - webServer.get('/some_endpoint', (req, res, next) => { - t.equals(req.headers.dnt, '1'); - - t.equals(req.headers.header1, 'header1 value', 'all headers should have been passed'); - t.deepEquals(req.query, { param1: 'param1 value', param2: 'param2 value' }); - - res.status(400).send('a bad request was made'); - }); - - const server = webServer.listen(); - const port = server.address().port; - - const logger = require('pelias-mock-logger')(); - - const MockServiceConfig = class extends ServiceConfiguration { - constructor(o) { - super('foo', { url: `http://localhost:${port}` } ); - } - getUrl(req) { - return `http://localhost:${port}/some_endpoint`; - } - getParameters(req) { - return { param1: 'param1 value', param2: 'param2 value' }; - } - getHeaders(req) { - return { header1: 'header1 value' }; - } - }; - - const service = proxyquire('../../../service/http_json', { - 'pelias-logger': logger, - '../helper/logging': { - isDNT: () => { return true; } - } - })(new MockServiceConfig()); - - t.ok(logger.isInfoMessage(new RegExp(`using foo service at http://localhost:${port}`))); - - service({}, (err, results) => { - t.equals(err, `http://localhost:${port} [do_not_track] returned status 400: a bad request was made`); - t.notOk(results); - t.ok(logger.isErrorMessage(`http://localhost:${port} [do_not_track] ` + - `returned status 400: a bad request was made`)); - t.end(); - - server.close(); - - }); - - }); - - test('server returning 200 statusCode but with non-JSON response should log error and return undefined', (t) => { - const webServer = express(); - webServer.get('/some_endpoint', (req, res, next) => { - t.notOk(req.headers.hasOwnProperty('dnt'), 'dnt header should not have been passed'); - - t.equals(req.headers.header1, 'header1 value', 'all headers should have been passed'); - t.deepEquals(req.query, { param1: 'param1 value', param2: 'param2 value' }); - - res.set('Content-Type', 'text/plain').status(200).send('this is not parseable as JSON'); - }); - - const server = webServer.listen(); - const port = server.address().port; - - const logger = require('pelias-mock-logger')(); - - const MockServiceConfig = class extends ServiceConfiguration { - constructor(o) { - super('foo', { url: `http://localhost:${port}` } ); - } - getUrl(req) { - return `http://localhost:${port}/some_endpoint`; - } - getParameters(req) { - return { param1: 'param1 value', param2: 'param2 value' }; - } - getHeaders(req) { - return { header1: 'header1 value' }; - } - }; - - const service = proxyquire('../../../service/http_json', { - 'pelias-logger': logger - })(new MockServiceConfig()); - - t.ok(logger.isInfoMessage(new RegExp(`using foo service at http://localhost:${port}`))); - - service({}, (err, results) => { - t.equals(err, `http://localhost:${port}/some_endpoint?param1=param1%20value¶m2=param2%20value ` + - `could not parse response: this is not parseable as JSON`); - t.notOk(results, 'should return undefined'); - t.ok(logger.isErrorMessage(`http://localhost:${port}/some_endpoint?param1=param1%20value¶m2=param2%20value ` + - `could not parse response: this is not parseable as JSON`)); - t.end(); - - server.close(); - - }); - - }); - - test('[DNT] server returning 200 statusCode but with non-JSON response should log sanitized error and return undefined', (t) => { - const webServer = express(); - webServer.get('/some_endpoint', (req, res, next) => { - t.equals(req.headers.dnt, '1'); - - t.equals(req.headers.header1, 'header1 value', 'all headers should have been passed'); - t.deepEquals(req.query, { param1: 'param1 value', param2: 'param2 value' }); - - res.status(200).send('this is not parseable as JSON'); - }); - - const server = webServer.listen(); - const port = server.address().port; - - const logger = require('pelias-mock-logger')(); - - const MockServiceConfig = class extends ServiceConfiguration { - constructor(o) { - super('foo', { url: `http://localhost:${port}` } ); - } - getUrl(req) { - return `http://localhost:${port}/some_endpoint`; - } - getParameters(req) { - return { param1: 'param1 value', param2: 'param2 value' }; - } - getHeaders(req) { - return { header1: 'header1 value' }; - } - }; - - const service = proxyquire('../../../service/http_json', { - 'pelias-logger': logger, - '../helper/logging': { - isDNT: () => { return true; } - } - })(new MockServiceConfig()); - - t.ok(logger.isInfoMessage(new RegExp(`using foo service at http://localhost:${port}`))); - - service({}, (err, results) => { - t.equals(err, `http://localhost:${port} [do_not_track] ` + - `could not parse response: this is not parseable as JSON`); - t.notOk(results, 'should return undefined'); - t.ok(logger.isErrorMessage(`http://localhost:${port} [do_not_track] ` + - `could not parse response: this is not parseable as JSON`)); - t.end(); - - server.close(); - - }); - - }); - - test('server timing out on all requests should log and return error', (t) => { - const webServer = express(); - let requestCount = 0; - webServer.get('/some_endpoint', (req, res, next) => { - requestCount++; - res.set('Content-Type', 'text/plain').status(503).send('request timeout'); - }); - - const server = webServer.listen(); - const port = server.address().port; - - const logger = require('pelias-mock-logger')(); - - const MockServiceConfig = class extends ServiceConfiguration { - constructor(o) { - super('foo', { url: `http://localhost:${port}` } ); - } - getUrl(req) { - return `http://localhost:${port}/some_endpoint`; - } - getParameters(req) { - return { param1: 'param1 value', param2: 'param2 value' }; - } - getHeaders(req) { - return { header1: 'header1 value' }; - } - getRetries() { - return 1; - } - }; - - const service = proxyquire('../../../service/http_json', { - 'pelias-logger': logger - })(new MockServiceConfig()); - - t.ok(logger.isInfoMessage(new RegExp(`using foo service at http://localhost:${port}`))); - - service({}, (err, results) => { - t.equals(err, `http://localhost:${port}/some_endpoint?param1=param1%20value¶m2=param2%20value ` + - 'returned status 503: request timeout'); - t.notOk(results); - t.ok(logger.isErrorMessage(`http://localhost:${port}/some_endpoint?param1=param1%20value¶m2=param2%20value ` + - `returned status 503: request timeout`)); - t.equals(requestCount, 2); - t.end(); - - server.close(); - - }); - - }); - -}; - -module.exports.tests.success_conditions = (test, common) => { - test('server returning statusCode 200 should return no error and parsed output', (t) => { - const webServer = express(); - webServer.get('/some_endpoint', (req, res, next) => { - t.notOk(req.headers.hasOwnProperty('dnt'), 'dnt header should not have been passed'); - - t.equals(req.headers.header1, 'header1 value', 'all headers should have been passed'); - t.deepEquals(req.query, { param1: 'param1 value', param2: 'param2 value' }); - - res.status(200).json([1, 2, 3]); - }); - - const server = webServer.listen(); - const port = server.address().port; - - const logger = require('pelias-mock-logger')(); - - const MockServiceConfig = class extends ServiceConfiguration { - constructor(o) { - super('foo', { url: `http://localhost:${port}` } ); - } - getUrl(req) { - return `http://localhost:${port}/some_endpoint`; - } - getParameters(req) { - return { param1: 'param1 value', param2: 'param2 value' }; - } - getHeaders(req) { - return { header1: 'header1 value' }; - } - }; - - const service = proxyquire('../../../service/http_json', { - 'pelias-logger': logger - })(new MockServiceConfig()); - - t.ok(logger.isInfoMessage(new RegExp(`using foo service at http://localhost:${port}`))); - - service({}, (err, results) => { - t.notOk(err, 'should be no error'); - t.deepEquals(results, [1, 2, 3]); - t.notOk(logger.hasErrorMessages()); - t.end(); - - server.close(); - - }); - - }); - - test('getHeaders returning undefined should use empty headers object', (t) => { - const webServer = express(); - webServer.get('/some_endpoint', (req, res, next) => { - t.equals(req.headers.dnt, '1'); - - t.deepEquals(req.query, { param1: 'param1 value', param2: 'param2 value' }); - - res.status(200).json([1, 2, 3]); - }); - - const server = webServer.listen(); - const port = server.address().port; - - const logger = require('pelias-mock-logger')(); - - const MockServiceConfig = class extends ServiceConfiguration { - constructor(o) { - super('foo', { url: `http://localhost:${port}` } ); - } - getUrl(req) { - return `http://localhost:${port}/some_endpoint`; - } - getParameters(req) { - return { param1: 'param1 value', param2: 'param2 value' }; - } - getHeaders(req) { - return undefined; - } - }; - - const service = proxyquire('../../../service/http_json', { - 'pelias-logger': logger, - '../helper/logging': { - isDNT: () => { return true; } - } - })(new MockServiceConfig()); - - t.ok(logger.isInfoMessage(new RegExp(`using foo service at http://localhost:${port}`))); - - service({}, (err, results) => { - t.notOk(err, 'should be no error'); - t.deepEquals(results, [1, 2, 3]); - t.notOk(logger.hasErrorMessages()); - t.end(); - - server.close(); - - }); - - }); - - test('server succeeding on last timeout chance should return no error and parsed output', (t) => { - const webServer = express(); - let requestCount = 0; - webServer.get('/some_endpoint', (req, res, next) => { - if (++requestCount < 3) { - res.status(503); - - } else { - t.notOk(req.headers.hasOwnProperty('dnt'), 'dnt header should not have been passed'); - t.equals(req.headers.header1, 'header1 value', 'all headers should have been passed'); - t.deepEquals(req.query, { param1: 'param1 value', param2: 'param2 value' }); - - res.status(200).json([1, 2, 3]); - - } - - }); - - const server = webServer.listen(); - const port = server.address().port; - - const logger = require('pelias-mock-logger')(); - - const MockServiceConfig = class extends ServiceConfiguration { - constructor(o) { - super('foo', { url: `http://localhost:${port}` } ); - } - getUrl(req) { - return `http://localhost:${port}/some_endpoint`; - } - getParameters(req) { - return { param1: 'param1 value', param2: 'param2 value' }; - } - getHeaders(req) { - return { header1: 'header1 value' }; - } - }; - - const service = proxyquire('../../../service/http_json', { - 'pelias-logger': logger - })(new MockServiceConfig()); - - t.ok(logger.isInfoMessage(new RegExp(`using foo service at http://localhost:${port}`))); - - service({}, (err, results) => { - t.notOk(err, 'should be no error'); - t.deepEquals(results, [1, 2, 3]); - t.notOk(logger.hasErrorMessages()); - t.equals(requestCount, 3); - t.end(); - - server.close(); - - }); - - }); - -}; - -module.exports.all = (tape, common) => { - function test(name, testFunction) { - return tape(`SERVICE /http_json ${name}`, testFunction); - } - - for( var testCase in module.exports.tests ){ - module.exports.tests[testCase](test, common); - } -};