UNPKG

nice-cloud-config-client

Version:
168 lines (156 loc) 5.09 kB
'use strict' /** * @module CloudConfigClient */ const http = require('http') const https = require('https') const DEFAULT_URL = new URL('http://localhost:8888') const Config = require('./lib/config') /** * Client auth configuration * * @typedef {Object} Auth * @property {string} user - user id. * @property {string} pass - user password. */ /** * Client configuration * * @typedef {Object} Options * @property {string} [endpoint=http://localhost:8888] - spring config service url * @property {boolean} [rejectUnauthorized=true] - if false accepts self-signed certificates * @property {string} [application] - <b>deprecated</b> use name * @property {string} name - application id * @property {(string|string[])} [profiles="default"] - application profiles (e.g. ["test", "timeout"] or "test,timeout") * @property {string} [label] - environment id * @property {module:CloudConfigClient~Auth} [auth] - auth configuration * @property {http.Agent|https.Agent} [agent] - Agent for the request. (e.g. use a proxy) (Since version 1.2.0) * @property {object} [context] - Context for substitution (see context section below) (Since version 1.4.0) */ /** * Handle load response * * @callback loadCallback * @param {?Error} error - whether there was an error retrieving configurations * @param {module:Config~Config} config - configuration object instance */ /** * Retrieve basic auth from options * * Priority: * 1. Defined in options * 2. Coded as basic auth in url * * @param {module:CloudConfigClient~Auth} auth - auth configuration. * @param {URL} url - endpoint. * @returns {string} basic auth. */ function getAuth (auth, url) { if (auth && auth.user && auth.pass) { return auth.user + ':' + auth.pass } return url.username + ':' + url.password } /** * Build profile string from options value * * @param {(string|string[])} [profiles] - list of profiles, if none specified will use 'default' */ function buildProfilesString (profiles) { if (!profiles) { return 'default' } if (Array.isArray(profiles)) { return profiles.join(',') } return profiles } /** * Build spring config endpoint path * * @param {string} path - host base path * @param {string} name - application name * @param {(string|string[])} [profiles] - list of profiles, if none specified will use 'default' * @param {string} [label] - environment id * @returns {string} spring config endpoint */ function getPath (path, name, profiles, label) { const profilesStr = buildProfilesString(profiles) return (path.endsWith('/') ? path : path + '/') + encodeURIComponent(name) + '/' + encodeURIComponent(profilesStr) + (label ? '/' + encodeURIComponent(label) : '') } /** * Load configuration with callback * * @param {module:CloudConfigClient~Options} options - spring client configuration options * @param {module:CloudConfigClient~loadCallback} [callback] - load callback */ function loadWithCallback (options, callback) { const endpoint = options.endpoint ? new URL(options.endpoint) : DEFAULT_URL const name = options.name || options.application const context = options.context const client = endpoint.protocol === 'https:' ? https : http client.request({ protocol: endpoint.protocol, hostname: endpoint.hostname, port: endpoint.port, path: getPath(endpoint.pathname, name, options.profiles, options.label), auth: getAuth(options.auth, endpoint), rejectUnauthorized: options.rejectUnauthorized !== false, agent: options.agent, headers: options.headers }, (res) => { if (res.statusCode !== 200) { // OK res.resume() // it consumes response return callback(new Error('Invalid response: ' + res.statusCode)) } let response = '' res.setEncoding('utf8') res.on('data', (data) => { response += data }) res.on('end', () => { try { const body = JSON.parse(response) callback(null, new Config(body, context)) } catch (e) { callback(e) } }) }).on('error', callback).end() } /** * Wrap loadWithCallback with Promise * * @param {module:CloudConfigClient~Options} options - spring client configuration options * @returns {Promise<module:Config~Config, Error>} promise handler */ function loadWithPromise (options) { return new Promise((resolve, reject) => { loadWithCallback(options, (error, config) => { if (error) { reject(error) } else { resolve(config) } }) }) } module.exports = { /** * Retrieve properties from Spring Cloud config service * * @param {module:CloudConfigClient~Options} options - spring client configuration options * @param {module:CloudConfigClient~loadCallback} [callback] - load callback * @returns {Promise<module:Config~Config, Error>|void} promise handler or void if callback was not defined * * @since 1.0.0 */ load (options, callback) { return typeof callback === 'function' ? loadWithCallback(options, callback) : loadWithPromise(options) } }