diff --git a/src/cli/bin.js b/src/cli/bin.js old mode 100644 new mode 100755 diff --git a/src/cli/run.js b/src/cli/run.js index 8e48821e..4774691f 100644 --- a/src/cli/run.js +++ b/src/cli/run.js @@ -1,10 +1,41 @@ const cp = require("child_process"); -const getPort = require("get-port"); +const getNewPort = require("get-port"); +const http = require("http"); const servers = require("./servers"); const getCmd = require("../get-cmd"); +const daemonConf = require("../conf"); const signals = ["SIGINT", "SIGTERM", "SIGHUP"]; +function getPort(id) { + return new Promise((resolve, reject) => { + const { host, port } = daemonConf; + const options = { + host, + port, + path: `/_/servers/${id}/port`, + method: "GET" + }; + const req = http.request(options, res => { + let body = ""; + req.on("error", reject); + res.on("data", function(chunk) { + body += chunk; + }); + res.on("end", () => { + if (!res.complete) { + reject( + new Error("HTTP connection terminated before response complete") + ); + } + resolve(body ? parseInt(body, 10) : getNewPort()); + }); + }); + req.on("error", reject); + req.end(); + }); +} + module.exports = { // For testing purpose, allows stubbing cp.spawnSync _spawnSync(...args) { @@ -26,7 +57,7 @@ module.exports = { const serverAddress = `http://localhost:${port}`; process.env.PORT = port; - servers.add(serverAddress, opts); + servers.add(serverAddress, { ...opts, port }); signals.forEach(signal => process.on(signal, cleanAndExit)); @@ -43,7 +74,7 @@ module.exports = { if (opts.port) { startServer(opts.port); } else { - getPort() + getPort(servers.getId(opts)) .then(startServer) .catch(err => { throw err; diff --git a/src/cli/servers.js b/src/cli/servers.js index 4e2d673f..6dd7a377 100644 --- a/src/cli/servers.js +++ b/src/cli/servers.js @@ -10,7 +10,8 @@ const serversDir = common.serversDir; module.exports = { add, rm, - ls + ls, + getId }; function isUrl(str) { @@ -29,7 +30,9 @@ function domainify(str) { ); } -function getId(cwd) { +function getId(opts, cwd) { + if (opts.name) return domainify(opts.name); + if (!cwd) cwd = process.cwd(); return domainify(path.basename(cwd)); } @@ -41,7 +44,7 @@ function add(param, opts = {}) { mkdirp.sync(serversDir); const cwd = opts.dir || process.cwd(); - const id = opts.name ? domainify(opts.name) : getId(cwd); + const id = getId(opts, cwd); const force = opts.force; const file = getServerFile(id); @@ -97,11 +100,12 @@ function add(param, opts = {}) { } }); } + } - // Copy port option - if (opts.port) { - conf.env.PORT = opts.port; - } + // Copy port option + if (opts.port) { + if (!conf.env) conf.env = {}; + conf.env.PORT = opts.port; } const data = JSON.stringify(conf, null, 2); @@ -126,8 +130,7 @@ function add(param, opts = {}) { } function rm(opts = {}) { - const cwd = process.cwd(); - const id = opts.n || getId(cwd); + const id = getId(opts); const file = getServerFile(id); console.log(`Remove ${tildify(file)}`); diff --git a/src/daemon/group.js b/src/daemon/group.js index 439bc4bc..f4b5d996 100644 --- a/src/daemon/group.js +++ b/src/daemon/group.js @@ -21,6 +21,7 @@ class Group extends EventEmitter { super(); this._list = {}; + this._ports = {}; this._proxy = httpProxy.createProxyServer({ xfwd: true }); @@ -64,7 +65,15 @@ class Group extends EventEmitter { return this._list[id]; } + findPort(id) { + return this._ports[id]; + } + add(id, conf) { + if (conf.env && conf.env.PORT) { + this._ports[id] = conf.env.PORT; + } + if (conf.target) { log(`Add target ${id}`); this._list[id] = conf; diff --git a/src/daemon/routers/api/servers.js b/src/daemon/routers/api/servers.js index 2fde766e..55034029 100644 --- a/src/daemon/routers/api/servers.js +++ b/src/daemon/routers/api/servers.js @@ -7,6 +7,12 @@ module.exports = group => { res.json(group.list()); }); + router.get("/:id/port", (req, res) => { + const port = group.findPort(req.params.id); + if (port) res.json(port); + return res.end(); + }); + router.post( "/:id/start", group.exists.bind(group), diff --git a/test/cli/run.js b/test/cli/run.js index 140d5c4b..fdfdc822 100644 --- a/test/cli/run.js +++ b/test/cli/run.js @@ -32,7 +32,11 @@ test("spawn with port", t => { "should add a target" ); - t.is(servers.add.firstCall.args[1], opts, "should pass options to add"); + t.deepEqual( + servers.add.firstCall.args[1], + opts, + "should pass options to add" + ); t.true(servers.rm.called); t.is(servers.rm.firstCall.args[0], opts, "should use same options to remove");