From 0b1e17b53ea6753e33250359eb47863549da7f44 Mon Sep 17 00:00:00 2001 From: Nitin Kumar Date: Fri, 26 Mar 2021 18:55:18 +0530 Subject: [PATCH 1/3] feat: improve `host` option --- README.md | 1 - bin/cli-flags.js | 10 ------ lib/Server.js | 23 +++++++++++--- lib/options.json | 6 +--- lib/utils/createDomain.js | 5 +-- test/__snapshots__/Validation.test.js.snap | 2 +- test/cli/__snapshots__/cli.test.js.snap | 12 ++++++++ test/cli/cli.test.js | 36 ++++++++++++++++++++++ test/options.test.js | 4 --- test/server/utils/createDomain.test.js | 14 --------- 10 files changed, 69 insertions(+), 44 deletions(-) diff --git a/README.md b/README.md index b05b0519d8..2eb2bf82e1 100644 --- a/README.md +++ b/README.md @@ -96,7 +96,6 @@ Options: --setup-exit-signals Close and exit the process on SIGINT and SIGTERM. --no-setup-exit-signals Do not close and exit the process on SIGNIT and SIGTERM. --open [value] Open the default browser, or optionally specify a browser name. - --use-local-ip Open default browser with local IP. --open-page Open default browser with the specified page. --client-logging Log level in the browser (none, error, warn, info, log, verbose). --history-api-fallback Fallback to /index.html for Single Page Applications. diff --git a/bin/cli-flags.js b/bin/cli-flags.js index 28143bc5a0..a389d5b9f8 100644 --- a/bin/cli-flags.js +++ b/bin/cli-flags.js @@ -128,16 +128,6 @@ module.exports = { description: 'Open the default browser, or optionally specify a browser name.', }, - { - name: 'use-local-ip', - type: Boolean, - configs: [ - { - type: 'boolean', - }, - ], - description: 'Open default browser with local IP.', - }, { name: 'open-page', type: String, diff --git a/lib/Server.js b/lib/Server.js index 80f29db7ef..52385f9b57 100644 --- a/lib/Server.js +++ b/lib/Server.js @@ -518,8 +518,14 @@ class Server { this.server = http.createServer(this.app); } - this.server.on('error', (err) => { - throw err; + this.server.on('error', (error) => { + if (error.syscall === 'getaddrinfo') { + this.logger.error( + `Address "${this.hostname}" is not available. Try with a different value for "host" option.\n ${error}` + ); + process.exit(2); + } + throw error; }); } @@ -724,7 +730,15 @@ class Server { } listen(port, hostname, fn) { - this.hostname = hostname; + if (hostname === 'local-ip') { + this.hostname = internalIp.v4.sync() || internalIp.v6.sync(); + } else if (hostname === 'local-ipv4') { + this.hostname = internalIp.v4.sync(); + } else if (hostname === 'local-ipv6') { + this.hostname = internalIp.v6.sync(); + } else { + this.hostname = hostname; + } if (typeof port !== 'undefined' && port !== this.options.port) { this.logger.warn( @@ -737,8 +751,7 @@ class Server { // eslint-disable-next-line no-shadow .then((port) => { this.port = port; - - return this.server.listen(port, hostname, (error) => { + return this.server.listen(port, this.hostname, (error) => { if (this.options.hot || this.options.liveReload) { this.createSocketServer(); } diff --git a/lib/options.json b/lib/options.json index a3b358934d..b6f83c72a5 100644 --- a/lib/options.json +++ b/lib/options.json @@ -374,9 +374,6 @@ "enum": ["sockjs", "ws"] } ] - }, - "useLocalIp": { - "type": "boolean" } }, "errorMessage": { @@ -403,8 +400,7 @@ "public": "should be {String} (https://webpack.js.org/configuration/dev-server/#devserverpublic)", "setupExitSignals": "should be {Boolean} (https://webpack.js.org/configuration/dev-server/#devserversetupexitsignals)", "static": "should be {Boolean|String|Object|Array} (https://webpack.js.org/configuration/dev-server/#devserverstatic)", - "transportMode": "should be {String|Object} (https://webpack.js.org/configuration/dev-server/#devservertransportmode)", - "useLocalIp": "should be {Boolean} (https://webpack.js.org/configuration/dev-server/#devserveruselocalip)" + "transportMode": "should be {String|Object} (https://webpack.js.org/configuration/dev-server/#devservertransportmode)" } }, "additionalProperties": false diff --git a/lib/utils/createDomain.js b/lib/utils/createDomain.js index 4a46bd2fc3..72ea414d69 100644 --- a/lib/utils/createDomain.js +++ b/lib/utils/createDomain.js @@ -1,7 +1,6 @@ 'use strict'; const url = require('url'); -const ip = require('internal-ip'); function createDomain(options, server) { const protocol = options.https ? 'https' : 'http'; @@ -9,9 +8,7 @@ function createDomain(options, server) { // ipv6 detection is not required as 0.0.0.0 is just used as a placeholder let hostname; - if (options.useLocalIp) { - hostname = ip.v4.sync() || '0.0.0.0'; - } else if (server) { + if (server) { hostname = server.address().address; } else { hostname = '0.0.0.0'; diff --git a/test/__snapshots__/Validation.test.js.snap b/test/__snapshots__/Validation.test.js.snap index cfd457c202..7a24b7771a 100644 --- a/test/__snapshots__/Validation.test.js.snap +++ b/test/__snapshots__/Validation.test.js.snap @@ -43,5 +43,5 @@ exports[`Validation validation should fail validation for invalid \`static\` con exports[`Validation validation should fail validation for no additional properties 1`] = ` "Invalid configuration object. Object has been initialized using a configuration object that does not match the API schema. - configuration has an unknown property 'additional'. These properties are valid: - object { bonjour?, client?, compress?, dev?, firewall?, headers?, historyApiFallback?, host?, hot?, http2?, https?, liveReload?, onAfterSetupMiddleware?, onBeforeSetupMiddleware?, onListening?, open?, openPage?, port?, proxy?, public?, setupExitSignals?, static?, transportMode?, useLocalIp? }" + object { bonjour?, client?, compress?, dev?, firewall?, headers?, historyApiFallback?, host?, hot?, http2?, https?, liveReload?, onAfterSetupMiddleware?, onBeforeSetupMiddleware?, onListening?, open?, openPage?, port?, proxy?, public?, setupExitSignals?, static?, transportMode? }" `; diff --git a/test/cli/__snapshots__/cli.test.js.snap b/test/cli/__snapshots__/cli.test.js.snap index 5c02ceb695..c5799ad044 100644 --- a/test/cli/__snapshots__/cli.test.js.snap +++ b/test/cli/__snapshots__/cli.test.js.snap @@ -20,6 +20,18 @@ exports[`CLI --host : stderr 1`] = ` [webpack-dev-server] Content not from webpack is served from '/public' directory" `; +exports[`CLI --host : stderr 1`] = ` +" [webpack-dev-server] Project is running at: + [webpack-dev-server] On Your Network (IPv4): http://:/ + [webpack-dev-server] Content not from webpack is served from '/public' directory" +`; + +exports[`CLI --host : stderr 1`] = ` +" [webpack-dev-server] Project is running at: + [webpack-dev-server] On Your Network (IPv4): http://:/ + [webpack-dev-server] Content not from webpack is served from '/public' directory" +`; + exports[`CLI --host 0.0.0.0 (IPv4): stderr 1`] = ` " [webpack-dev-server] Project is running at: [webpack-dev-server] Loopback: http://localhost:/ diff --git a/test/cli/cli.test.js b/test/cli/cli.test.js index e2f5093013..7fb78d574e 100644 --- a/test/cli/cli.test.js +++ b/test/cli/cli.test.js @@ -189,6 +189,42 @@ describe('CLI', () => { .catch(done); }); + it('--host ', (done) => { + testBin('--host local-ip') + .then((output) => { + expect(normalizeStderr(output.stderr)).toMatchSnapshot('stderr'); + + done(); + }) + .catch(done); + }); + + it('--host ', (done) => { + testBin('--host local-ipv4') + .then((output) => { + expect(normalizeStderr(output.stderr)).toMatchSnapshot('stderr'); + + done(); + }) + .catch(done); + }); + + it('should throw error for invalid host', (done) => { + const cliPath = path.resolve(__dirname, '../../bin/webpack-dev-server.js'); + const cwd = path.resolve(__dirname, '../fixtures/cli'); + const cp = execa('node', [cliPath, '--host', 'invalid'], { cwd }); + + cp.stderr.on('data', (chunk) => { + expect(chunk.toString()).toContain( + `Address "invalid" is not available. Try with a different value for "host" option.` + ); + }); + + cp.on('exit', () => { + done(); + }); + }); + it('--host localhost --port 9999', (done) => { testBin('--host localhost --port 9999') .then((output) => { diff --git a/test/options.test.js b/test/options.test.js index 0139db3d2f..526f68d55e 100644 --- a/test/options.test.js +++ b/test/options.test.js @@ -500,10 +500,6 @@ describe('options', () => { }, ], }, - useLocalIp: { - success: [false], - failure: [''], - }, }; Object.keys(cases).forEach((key) => { diff --git a/test/server/utils/createDomain.test.js b/test/server/utils/createDomain.test.js index fa796d319e..1c9861c5f2 100644 --- a/test/server/utils/createDomain.test.js +++ b/test/server/utils/createDomain.test.js @@ -1,7 +1,6 @@ 'use strict'; const webpack = require('webpack'); -const internalIp = require('internal-ip'); const Server = require('../../../lib/Server'); const createDomain = require('../../../lib/utils/createDomain'); const [port1, port2] = require('../../ports-map').createDomain; @@ -89,19 +88,6 @@ describe('createDomain', () => { }, expected: [`https://myhost.test:${port2}`], }, - { - name: 'localIp', - options: { - useLocalIp: true, - port: port1, - }, - expected: [ - `http://${internalIp.v4.sync()}:${port1}`, - `https://localhost:${port1}`, - `https://127.0.0.1:${port1}`, - `https://[::1]:${port1}`, - ], - }, ]; tests.forEach((test) => { From cec58919c23f7c7b2bcd2e2a9246a6a44b0c2ab7 Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Mon, 29 Mar 2021 14:45:18 +0300 Subject: [PATCH 2/3] refactor: code --- lib/Server.js | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/lib/Server.js b/lib/Server.js index 52385f9b57..5e53798a34 100644 --- a/lib/Server.js +++ b/lib/Server.js @@ -519,12 +519,6 @@ class Server { } this.server.on('error', (error) => { - if (error.syscall === 'getaddrinfo') { - this.logger.error( - `Address "${this.hostname}" is not available. Try with a different value for "host" option.\n ${error}` - ); - process.exit(2); - } throw error; }); } @@ -731,11 +725,12 @@ class Server { listen(port, hostname, fn) { if (hostname === 'local-ip') { - this.hostname = internalIp.v4.sync() || internalIp.v6.sync(); + this.hostname = + internalIp.v4.sync() || '0.0.0.0' || internalIp.v6.sync() || '::'; } else if (hostname === 'local-ipv4') { - this.hostname = internalIp.v4.sync(); + this.hostname = internalIp.v4.sync() || '0.0.0.0'; } else if (hostname === 'local-ipv6') { - this.hostname = internalIp.v6.sync(); + this.hostname = internalIp.v6.sync() || '::'; } else { this.hostname = hostname; } @@ -957,11 +952,13 @@ class Server { if (!isFile) { return next(); } + // Serve a page that executes the javascript const queries = req._parsedUrl.search || ''; const responsePage = ``; + res.send(responsePage); - } catch (err) { + } catch (error) { return next(); } } From 6773c303e107788c6c28f52fef4fb4e64f676c03 Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Mon, 29 Mar 2021 14:55:44 +0300 Subject: [PATCH 3/3] test: fix --- test/cli/cli.test.js | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/test/cli/cli.test.js b/test/cli/cli.test.js index 7fb78d574e..23a9d364a5 100644 --- a/test/cli/cli.test.js +++ b/test/cli/cli.test.js @@ -209,22 +209,6 @@ describe('CLI', () => { .catch(done); }); - it('should throw error for invalid host', (done) => { - const cliPath = path.resolve(__dirname, '../../bin/webpack-dev-server.js'); - const cwd = path.resolve(__dirname, '../fixtures/cli'); - const cp = execa('node', [cliPath, '--host', 'invalid'], { cwd }); - - cp.stderr.on('data', (chunk) => { - expect(chunk.toString()).toContain( - `Address "invalid" is not available. Try with a different value for "host" option.` - ); - }); - - cp.on('exit', () => { - done(); - }); - }); - it('--host localhost --port 9999', (done) => { testBin('--host localhost --port 9999') .then((output) => {