diff --git a/compose.js b/compose.js index 2c7a103..80b77c3 100644 --- a/compose.js +++ b/compose.js @@ -102,14 +102,26 @@ module.exports = function (ary, wrap) { }, parse: parse, stringify: function (scope) { - var none - var _ary = ary.map(function (e) { - var v = e.stringify(scope) - if(!v) none = true - else return v - }) - if(none) return - return SE.stringify(_ary) + var _ary = [] + var v = proto.stringify(scope) + if(!v) return + else { + // if true, more than one hostname needs to be updated + if (v.split(';').length > 1) { + var addresses = v.split(';') + addresses.forEach(a => { + _ary.push(a) + }) + } + else _ary.push(v) + } + return _ary.map(e => { + var singleAddr = [e].concat(trans.map(t => { + return t.stringify(scope) + })) + + return SE.stringify(singleAddr) + }).join(';') } } } diff --git a/plugins/net.js b/plugins/net.js index a668ddf..bdeaa36 100644 --- a/plugins/net.js +++ b/plugins/net.js @@ -120,10 +120,15 @@ module.exports = ({ scope = 'device', host, port, external, allowHalfOpen, pause return null } - // Remove IPv6 scopeid suffix, if any, e.g. `%wlan0` - resultHost = resultHost.replace(/(\%\w+)$/, '') - - return toAddress(resultHost, port) + // convert to an array for easier formatting + if (isString(resultHost)) { + resultHost = [resultHost] + } + + return resultHost.map((h) => { + // Remove IPv6 scopeid suffix, if any, e.g. `%wlan0` + return toAddress(h.replace(/(\%\w+)$/, ''), port) + }).join(';') } } } diff --git a/plugins/ws.js b/plugins/ws.js index 88fd785..4ff4c21 100644 --- a/plugins/ws.js +++ b/plugins/ws.js @@ -130,19 +130,25 @@ module.exports = function (opts = {}) { const port = opts.server ? opts.server.address().port : opts.port const externalHost = targetScope === 'public' && opts.external - const resultHost = externalHost || opts.host || scopes.host(targetScope) + let resultHost = externalHost || opts.host || scopes.host(targetScope) if (resultHost == null) { // The device has no network interface for a given `targetScope`. return null } - return URL.format({ - protocol: secure ? 'wss' : 'ws', - slashes: true, - hostname: resultHost, - port: (secure ? port == 443 : port == 80) ? undefined : port - }) + if (typeof resultHost === 'string') { + resultHost = [resultHost] + } + + return resultHost.map((h) => { + return URL.format({ + protocol: secure ? 'wss' : 'ws', + slashes: true, + hostname: h, + port: (secure ? port == 443 : port == 80) ? undefined : port + }) + }).join(';') }, parse: function (str) { var addr = URL.parse(str) diff --git a/test/plugs.js b/test/plugs.js index 9294678..2377e10 100644 --- a/test/plugs.js +++ b/test/plugs.js @@ -460,3 +460,132 @@ tape('multiple scopes different hosts', function(t) { t.end() }) + +tape('net: external is a string', function (t) { + var net = Net({ + external: 'domain.de', + scope: 'public', + port: '9966', + server: { + key: null, + address: function () { return {port: 9966}} + }}) + t.equal(net.stringify('public'), 'net:domain.de:9966') + t.equal(net.stringify('local'), null) + t.equal(net.stringify('device'), null) + t.end() +}) + +tape('net: external is an array', function (t) { + var net = Net({ + external: ['domain.de', 'funtime.net'], + scope: 'public', + port: '9966', + server: { + key: null, + address: function () { return {port: 9966}} + }}) + t.equal(net.stringify('public'), 'net:domain.de:9966;net:funtime.net:9966') + t.equal(net.stringify('local'), null) + t.equal(net.stringify('device'), null) + t.end() +}) + +tape('net: external is an array w/ a single entry & shs transform', function (t) { + var net = Net({ + external: ['domain.de'], + scope: 'public', + port: '9966', + server: { + key: null, + address: function () { return {port: 9966}} + }}) + var combined = Compose([net, shs]) + t.equal( + combined.stringify('public'), + 'net:domain.de:9966~shs:+y42DK+BGzqvU00EWMKiyj4fITskSm+Drxq1Dt2s3Yw=' + ) + t.end() +}) + +tape('net: external is an array w/ multiple entries & shs transform', function (t) { + var net = Net({ + external: ['domain.de', 'funtime.net'], + scope: 'public', + port: '9966', + server: { + key: null, + address: function () { return {port: 9966}} + }}) + var combined = Compose([net, shs]) + t.equal( + combined.stringify('public'), + 'net:domain.de:9966~shs:+y42DK+BGzqvU00EWMKiyj4fITskSm+Drxq1Dt2s3Yw=;net:funtime.net:9966~shs:+y42DK+BGzqvU00EWMKiyj4fITskSm+Drxq1Dt2s3Yw=' + ) + t.end() +}) + +tape('ws: external is a string', function (t) { + var ws = Ws({ + external: 'domain.de', + scope: 'public', + port: '9966', + server: { + key: null, + address: function () { return {port: 9966}} + }}) + t.equal(ws.stringify('public'), 'ws://domain.de:9966') + t.equal(ws.stringify('local'), null) + t.equal(ws.stringify('device'), null) + t.end() +}) + + +tape('ws: external is an array', function (t) { + var ws = Ws({ + external: ['domain.de', 'funtime.net'], + scope: 'public', + port: '9966', + server: { + key: null, + address: function () { return {port: 9966}} + }}) + t.equal(ws.stringify('public'), 'ws://domain.de:9966;ws://funtime.net:9966') + t.equal(ws.stringify('local'), null) + t.equal(ws.stringify('device'), null) + t.end() +}) + +tape('ws: external is an array w/ a single entry & shs transform', function (t) { + var ws = Ws({ + external: ['domain.de'], + scope: 'public', + port: '9966', + server: { + key: null, + address: function () { return {port: 9966}} + }}) + var combined = Compose([ws, shs]) + t.equal( + combined.stringify('public'), + 'ws://domain.de:9966~shs:+y42DK+BGzqvU00EWMKiyj4fITskSm+Drxq1Dt2s3Yw=' + ) + t.end() +}) + +tape('ws: external is an array w/ multiple entries & shs transform', function (t) { + var ws = Ws({ + external: ['domain.de', 'funtime.net'], + scope: 'public', + port: '9966', + server: { + key: null, + address: function () { return {port: 9966}} + }}) + var combined = Compose([ws, shs]) + t.equal( + combined.stringify('public'), + 'ws://domain.de:9966~shs:+y42DK+BGzqvU00EWMKiyj4fITskSm+Drxq1Dt2s3Yw=;ws://funtime.net:9966~shs:+y42DK+BGzqvU00EWMKiyj4fITskSm+Drxq1Dt2s3Yw=' + ) + t.end() +}) \ No newline at end of file