diff --git a/package.json b/package.json index e46475ad..1e276aef 100644 --- a/package.json +++ b/package.json @@ -60,6 +60,7 @@ "once": "^1.3.2", "please-upgrade-node": "^3.0.0", "pug": "^2.0.0-beta11", + "punycode": "^2.1.0", "respawn": "^2.4.1", "server-ready": "^0.3.1", "strip-ansi": "^4.0.0", diff --git a/src/daemon/group.js b/src/daemon/group.js index c4501d8a..8f959fe9 100644 --- a/src/daemon/group.js +++ b/src/daemon/group.js @@ -10,6 +10,7 @@ const afterAll = require('after-all') const httpProxy = require('http-proxy') const serverReady = require('server-ready') const log = require('./log') +const normalize = require('./normalize') const tcpProxy = require('./tcp-proxy') const daemonConf = require('../conf') const getCmd = require('../get-cmd') @@ -61,15 +62,19 @@ class Group extends EventEmitter { return this._list[id] } - add(id, conf) { + add(name, conf) { + conf.name = name + const id = normalize(name) + if (conf.target) { - log(`Add target ${id}`) + log(`Add target ${name}`) this._list[id] = conf + this._change() return } - log(`Add server ${id}`) + log(`Add server ${name}`) const HTTP_PROXY = `http://127.0.0.1:${daemonConf.port}/proxy.pac` @@ -97,7 +102,8 @@ class Group extends EventEmitter { const mon = respawn(command, { ...conf, - maxRestarts: 0 + maxRestarts: 0, + name }) this._list[id] = mon @@ -145,7 +151,8 @@ class Group extends EventEmitter { this._change() } - remove(id, cb) { + remove(name, cb) { + const id = normalize(name) const item = this.find(id) if (item) { delete this._list[id] @@ -204,10 +211,8 @@ class Group extends EventEmitter { exists(req, res, next) { // Resolve using either hostname `app.tld` // or id param `http://localhost:2000/app` - const tld = new RegExp(`.${daemonConf.tld}$`) - const id = req.params.id - ? this.resolve(req.params.id) - : this.resolve(req.hostname.replace(tld, '')) + const tld = new RegExp(`\\.${daemonConf.tld}$`) + const id = this.resolve(req.params.id || req.hostname.replace(tld, '')) // Find item const item = this.find(id) diff --git a/src/daemon/normalize.js b/src/daemon/normalize.js new file mode 100644 index 00000000..035276ff --- /dev/null +++ b/src/daemon/normalize.js @@ -0,0 +1,12 @@ +const punycode = require('punycode') // eslint-disable-line node/no-deprecated-api + +module.exports = function normalize(name) { + return name + ? punycode + .encode(name) + .toLowerCase() + .replace(/[^a-z0-9-.]/g, '-') + .replace(/-+/g, '-') + .replace(/-$/, '') + : name +} diff --git a/src/front/App.vue b/src/front/App.vue index bf1e3d45..da33416d 100644 --- a/src/front/App.vue +++ b/src/front/App.vue @@ -26,7 +26,7 @@ {{ id }} + target="_blank">{{ item.name }}
+ \ No newline at end of file diff --git a/test/daemon/group.js b/test/daemon/group.js index b0517679..f9f30f7e 100644 --- a/test/daemon/group.js +++ b/test/daemon/group.js @@ -19,6 +19,55 @@ test('group.resolve should find the correct server or target id', t => { t.is(group.resolve('baz.foo.app'), 'foo.app') }) +test('group.exists should 404 on missing id', t => { + const group = Group() + const conf = { target: 'http://example.com' } + + group.add('app', conf) + + const request = { params: { id: 'bar' }, hostname: 'localhost' } + + const sendSpy = sinon.stub() + const statusSpy = sinon.stub().returns({ send: sendSpy }) + const response = { status: statusSpy } + + group.exists(request, response) + + t.is(statusSpy.callCount, 1) + t.is(statusSpy.lastCall.args[0], 404) + t.is(sendSpy.callCount, 1) +}) + +test.cb('group.exists should find group by param', t => { + const group = Group() + const conf = { target: 'http://example.com' } + + group.add('App Foo', conf) + + const request = { params: { id: 'app-foo' }, hostname: 'localhost' } + const response = {} + + group.exists(request, response, () => { + t.is(request.hotel.id, 'app-foo') + t.end() + }) +}) + +test.cb('group.exists should find group by hostname', t => { + const group = Group() + const conf = { target: 'http://example.com' } + + group.add('bar-baz-∫', conf) + + const request = { params: {}, hostname: 'bar-baz-tl7d.dev' } + const response = {} + + group.exists(request, response, () => { + t.is(request.hotel.id, 'bar-baz-tl7d') + t.end() + }) +}) + test('group.handleUpgrade with proxy', t => { const group = Group() const target = 'example.com'