mirror of https://github.com/pelias/api.git
Stephen Hess
8 years ago
9 changed files with 29 additions and 788 deletions
@ -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; |
|
@ -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}`); |
|
||||||
} |
|
||||||
|
|
||||||
}); |
|
||||||
|
|
||||||
}; |
|
||||||
|
|
||||||
}; |
|
@ -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); |
|
||||||
} |
|
||||||
}; |
|
@ -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); |
|
||||||
} |
|
||||||
}; |
|
Loading…
Reference in new issue