-
Notifications
You must be signed in to change notification settings - Fork 33
/
Copy pathindex.js
174 lines (162 loc) · 5.18 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
'use strict'
/**
* @module CloudConfigClient
*/
const http = require('http')
const https = require('https')
// Support node 8
const URL_TYPE = typeof URL === 'undefined' ? require('url').URL : URL
const DEFAULT_URL = new URL_TYPE('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)
* @property {object} [headers] - Additional headers
*/
/**
* 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
}
if (url.username || url.password) {
return url.username + ':' + url.password
}
return null
}
/**
* 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_TYPE(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)
}
}