From 3dd4f013702f2812ad5c9776acbff9f4e801adaf Mon Sep 17 00:00:00 2001 From: delvedor Date: Fri, 9 Nov 2018 17:15:29 +0100 Subject: [PATCH] WIP: initial prototype - Renamed host configuration, now we use node(s) - Updated Connection internals - Added custom headers for Connection --- index.js | 8 +-- lib/Connection.js | 113 +++++++++++++++++++----------------------- lib/ConnectionPool.js | 4 +- 3 files changed, 56 insertions(+), 69 deletions(-) diff --git a/index.js b/index.js index 9896f59be..4ddd5b67c 100644 --- a/index.js +++ b/index.js @@ -19,8 +19,8 @@ const { class Client extends EventEmitter { constructor (opts = {}) { super() - if (!opts.host) { - throw new ConfigurationError('Missing host option') + if (!opts.node && !opts.nodes) { + throw new ConfigurationError('Missing node(s) option') } if (opts.log === true) { @@ -70,7 +70,7 @@ class Client extends EventEmitter { }) // Add the connections before initialize the Transport - this[kConnectionPool].addConnection(options.host) + this[kConnectionPool].addConnection(options.node || options.nodes) this[kTransport] = new options.Transport({ emit: this.emit.bind(this), @@ -110,5 +110,5 @@ module.exports = { Transport, ConnectionPool, Serializer, - symbols + ...symbols } diff --git a/lib/Connection.js b/lib/Connection.js index 5d16d0d58..bb17190b6 100644 --- a/lib/Connection.js +++ b/lib/Connection.js @@ -9,11 +9,10 @@ const { TimeoutError } = require('./errors') class Connection { constructor (opts = {}) { - assert(opts.host, 'Missing host data') - - this.host = urlToOptions(opts.host) - this.ssl = opts.host.ssl || opts.ssl || null - this.id = opts.id || opts.host.href + this.url = opts.url + this.ssl = opts.ssl || null + this.id = opts.id || opts.url.href + this.headers = opts.headers || null this.deadCount = 0 this.resurrectTimeout = 0 @@ -26,12 +25,12 @@ class Connection { keepAliveMsecs: 1000, maxSockets: Infinity, maxFreeSockets: 256 - }, opts.host.agent || opts.agent) - this._agent = this.host.protocol === 'http:' + }, opts.agent || opts.agent) + this._agent = this.url.protocol === 'http:' ? new http.Agent(agentOptions) : new https.Agent(Object.assign({}, agentOptions, this.ssl)) - this.makeRequest = this.host.protocol === 'http:' + this.makeRequest = this.url.protocol === 'http:' ? http.request : https.request } @@ -42,7 +41,7 @@ class Connection { params.agent = this._agent debug('Starting a new request', params) - const request = this.makeRequest(buildRequestObject(this.host, params)) + const request = this.makeRequest(this.buildRequestObject(params)) // listen for the response event // TODO: handle redirects? @@ -115,6 +114,48 @@ class Connection { ) this._status = status } + + buildRequestObject (params) { + const url = this.url + const request = { + protocol: url.protocol, + hostname: url.hostname[0] === '[' + ? url.hostname.slice(1, -1) + : url.hostname, + hash: url.hash, + search: url.search, + pathname: url.pathname, + path: '', + href: url.href, + port: url.port, + headers: this.headers, + auth: !!url.username === true || !!url.password === true + ? `${url.username}:${url.password}` + : undefined + } + + const paramsKeys = Object.keys(params) + for (var i = 0, len = paramsKeys.length; i < len; i++) { + var key = paramsKeys[i] + if (key === 'path') { + request.pathname = resolve(request.pathname, params[key]) + } else if (key === 'querystring' && !!params[key] === true) { + if (request.search === '') { + request.search = '?' + params[key] + } else { + request.search += '&' + params[key] + } + } else if (key === 'headers') { + request.headers = Object.assign({}, request.headers, params.headers) + } else { + request[key] = params[key] + } + } + + request.path = request.pathname + request.search + + return request + } } Connection.statuses = { @@ -156,58 +197,4 @@ function resolve (host, path) { } } -function buildRequestObject (host, request) { - var merged = {} - var hostKeys = Object.keys(host) - var requestKeys = Object.keys(request) - - for (var i = 0, len = hostKeys.length; i < len; i++) { - var key = hostKeys[i] - merged[key] = host[key] - } - - for (i = 0, len = requestKeys.length; i < len; i++) { - key = requestKeys[i] - if (key === 'path') { - merged.pathname = resolve(merged.pathname, request[key]) - } else if (key === 'querystring' && !!request[key] === true) { - if (merged.search === '') { - merged.search = '?' + request[key] - } else { - merged.search += '&' + request[key] - } - } else { - merged[key] = request[key] - } - } - - merged.path = merged.pathname + merged.search - - return merged -} - -// Utility function that converts a URL object into an ordinary -// options object as expected by the http.request and https.request APIs. -// https://github.com/nodejs/node/blob/v11.0.0/lib/internal/url.js#L1324 -function urlToOptions (url) { - var options = { - protocol: url.protocol, - hostname: url.hostname.startsWith('[') - ? url.hostname.slice(1, -1) - : url.hostname, - hash: url.hash, - search: url.search, - pathname: url.pathname, - path: `${url.pathname}${url.search}`, - href: url.href - } - if (url.port !== '') { - options.port = Number(url.port) - } - if (url.username || url.password) { - options.auth = `${url.username}:${url.password}` - } - return options -} - module.exports = Connection diff --git a/lib/ConnectionPool.js b/lib/ConnectionPool.js index fdf48e96e..a42832ca0 100644 --- a/lib/ConnectionPool.js +++ b/lib/ConnectionPool.js @@ -290,7 +290,7 @@ class ConnectionPool { ? address : 'http://' + address hosts.push({ - host: new URL(address), + url: new URL(address), id: ids[i], roles: node.roles.reduce((acc, role) => { acc[role] = true @@ -310,7 +310,7 @@ class ConnectionPool { */ urlToHost (url) { return { - host: new URL(url) + url: new URL(url) } } }