Skip to content

Commit 33dc4fe

Browse files
authored
refactor: avoid new public options on class (#3261)
1 parent 1c83533 commit 33dc4fe

File tree

5 files changed

+221
-48
lines changed

5 files changed

+221
-48
lines changed

lib/Server.js

Lines changed: 59 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ const routes = require('./utils/routes');
1414
const getSocketServerImplementation = require('./utils/getSocketServerImplementation');
1515
const getCompilerConfigArray = require('./utils/getCompilerConfigArray');
1616
const setupExitSignals = require('./utils/setupExitSignals');
17+
const getStatsOption = require('./utils/getStatsOption');
18+
const getColorsOption = require('./utils/getColorsOption');
1719
const schema = require('./options.json');
1820

1921
if (!process.env.WEBPACK_SERVE) {
@@ -40,6 +42,7 @@ class Server {
4042
this.wsHeartbeatInterval = 30000;
4143

4244
normalizeOptions(this.compiler, this.options);
45+
4346
this.applyDevServerPlugin();
4447

4548
this.SocketServerImplementation = getSocketServerImplementation(
@@ -629,8 +632,6 @@ class Server {
629632
}
630633

631634
showStatus() {
632-
const getColorsOption = require('./utils/getColorsOption');
633-
634635
const useColor = getColorsOption(getCompilerConfigArray(this.compiler));
635636
const protocol = this.options.https ? 'https' : 'http';
636637
const { address, port } = this.server.address();
@@ -644,20 +645,20 @@ class Server {
644645
let networkUrlIPv4;
645646
let networkUrlIPv6;
646647

647-
if (this.hostname) {
648-
if (this.hostname === 'localhost') {
648+
if (this.options.host) {
649+
if (this.options.host === 'localhost') {
649650
localhost = prettyPrintUrl('localhost');
650651
} else {
651652
let isIP;
652653

653654
try {
654-
isIP = ipaddr.parse(this.hostname);
655+
isIP = ipaddr.parse(this.options.host);
655656
} catch (error) {
656657
// Ignore
657658
}
658659

659660
if (!isIP) {
660-
server = prettyPrintUrl(this.hostname);
661+
server = prettyPrintUrl(this.options.host);
661662
}
662663
}
663664
}
@@ -754,36 +755,62 @@ class Server {
754755
if (this.options.open) {
755756
const runOpen = require('./utils/runOpen');
756757

757-
const openTarget = prettyPrintUrl(this.hostname || 'localhost');
758+
const openTarget = prettyPrintUrl(this.options.host || 'localhost');
758759

759760
runOpen(openTarget, this.options.open, this.logger);
760761
}
761762
}
762763

763764
listen(port, hostname, fn) {
764-
if (hostname === 'local-ip') {
765-
this.hostname = internalIp.v4.sync() || internalIp.v6.sync() || '0.0.0.0';
766-
} else if (hostname === 'local-ipv4') {
767-
this.hostname = internalIp.v4.sync() || '0.0.0.0';
768-
} else if (hostname === 'local-ipv6') {
769-
this.hostname = internalIp.v6.sync() || '::';
770-
} else {
771-
this.hostname = hostname;
765+
if (
766+
typeof port !== 'undefined' &&
767+
typeof this.options.port !== 'undefined' &&
768+
port !== this.options.port
769+
) {
770+
this.options.port = port;
771+
772+
this.logger.warn(
773+
'The "port" specified in options is different from the port passed as an argument. Will be used from arguments.'
774+
);
775+
}
776+
777+
if (!this.options.port) {
778+
this.options.port = port;
772779
}
773780

774-
if (typeof port !== 'undefined' && port !== this.options.port) {
781+
if (
782+
typeof hostname !== 'undefined' &&
783+
typeof this.options.host !== 'undefined' &&
784+
hostname !== this.options.host
785+
) {
786+
this.options.host = hostname;
787+
775788
this.logger.warn(
776-
'The port specified in options and the port passed as an argument is different.'
789+
'The "host" specified in options is different from the host passed as an argument. Will be used from arguments.'
777790
);
778791
}
779792

780-
return (
781-
Server.getFreePort(port || this.options.port)
782-
// eslint-disable-next-line no-shadow
783-
.then((port) => {
784-
this.options.port = port;
793+
if (!this.options.host) {
794+
this.options.host = hostname;
795+
}
796+
797+
if (this.options.host === 'local-ip') {
798+
this.options.host =
799+
internalIp.v4.sync() || internalIp.v6.sync() || '0.0.0.0';
800+
} else if (this.options.host === 'local-ipv4') {
801+
this.options.host = internalIp.v4.sync() || '0.0.0.0';
802+
} else if (this.options.host === 'local-ipv6') {
803+
this.options.host = internalIp.v6.sync() || '::';
804+
}
805+
806+
return Server.getFreePort(this.options.port)
807+
.then((foundPort) => {
808+
this.options.port = foundPort;
785809

786-
return this.server.listen(port, this.hostname, (error) => {
810+
return this.server.listen(
811+
this.options.port,
812+
this.options.host,
813+
(error) => {
787814
if (this.options.hot || this.options.liveReload) {
788815
this.createSocketServer();
789816
}
@@ -803,14 +830,14 @@ class Server {
803830
if (typeof this.options.onListening === 'function') {
804831
this.options.onListening(this);
805832
}
806-
});
807-
})
808-
.catch((error) => {
809-
if (fn) {
810-
fn.call(this.server, error);
811833
}
812-
})
813-
);
834+
);
835+
})
836+
.catch((error) => {
837+
if (fn) {
838+
fn.call(this.server, error);
839+
}
840+
});
814841
}
815842

816843
close(cb) {
@@ -874,8 +901,6 @@ class Server {
874901
}
875902

876903
getStats(statsObj) {
877-
const getStatsOption = require('./utils/getStatsOption');
878-
879904
const stats = Server.DEFAULT_STATS;
880905

881906
const configArr = getCompilerConfigArray(this.compiler);
@@ -950,12 +975,12 @@ class Server {
950975
// these are removed from the hostname in url.parse(),
951976
// so we have the pure IPv6-address in hostname.
952977
// always allow localhost host, for convenience (hostname === 'localhost')
953-
// allow hostname of listening address (hostname === this.hostname)
978+
// allow hostname of listening address (hostname === this.options.host)
954979
const isValidHostname =
955980
ipaddr.IPv4.isValid(hostname) ||
956981
ipaddr.IPv6.isValid(hostname) ||
957982
hostname === 'localhost' ||
958-
hostname === this.hostname;
983+
hostname === this.options.host;
959984

960985
if (isValidHostname) {
961986
return true;

test/helpers/test-server.js

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,19 +21,25 @@ function startFullSetup(config, options, done) {
2121
server = new Server(options, compiler);
2222

2323
let port;
24+
2425
if (Object.prototype.hasOwnProperty.call(options, 'port')) {
2526
port = options.port;
2627
} else {
2728
console.warn('Using the default port for testing is not recommended');
2829
port = 8080;
2930
}
30-
const host = Object.prototype.hasOwnProperty.call(options, 'host')
31-
? options.host
32-
: 'localhost';
3331

34-
server.listen(port, host, (err) => {
35-
if (err && done) {
36-
return done(err);
32+
let host;
33+
34+
if (Object.prototype.hasOwnProperty.call(options, 'host')) {
35+
host = options.host;
36+
} else {
37+
host = 'localhost';
38+
}
39+
40+
server.listen(port, host, (error) => {
41+
if (error && done) {
42+
return done(error);
3743
}
3844

3945
if (done) {

test/server/Server.test.js

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ jest.mock('sockjs/lib/transport');
1616

1717
const baseDevConfig = {
1818
port,
19+
host: 'localhost',
1920
static: false,
2021
};
2122

@@ -161,6 +162,130 @@ describe('Server', () => {
161162
});
162163
});
163164

165+
describe('listen', () => {
166+
let compiler;
167+
let server;
168+
169+
beforeAll(() => {
170+
compiler = webpack(config);
171+
});
172+
173+
it('should work and using "port" and "host" from options', (done) => {
174+
const options = {
175+
host: 'localhost',
176+
port,
177+
};
178+
179+
server = new Server(options, compiler);
180+
181+
// eslint-disable-next-line no-undefined
182+
server.listen(undefined, undefined, () => {
183+
const info = server.server.address();
184+
185+
expect(info.address).toBe('127.0.0.1');
186+
expect(info.port).toBe(port);
187+
188+
server.close(done);
189+
});
190+
});
191+
192+
it('should work and using "port" and "host" from arguments', (done) => {
193+
server = new Server({}, compiler);
194+
195+
server.listen(port, '127.0.0.1', () => {
196+
const info = server.server.address();
197+
198+
expect(info.address).toBe('127.0.0.1');
199+
expect(info.port).toBe(port);
200+
201+
server.close(done);
202+
});
203+
});
204+
205+
it('should work and using the same "port" and "host" from options and arguments', (done) => {
206+
const options = {
207+
host: 'localhost',
208+
port,
209+
};
210+
211+
server = new Server(options, compiler);
212+
213+
server.listen(options.port, options.host, () => {
214+
const info = server.server.address();
215+
216+
expect(info.address).toBe('127.0.0.1');
217+
expect(info.port).toBe(port);
218+
219+
server.close(done);
220+
});
221+
});
222+
223+
it('should work and using "port" from arguments and "host" from options', (done) => {
224+
const options = {
225+
host: '127.0.0.1',
226+
};
227+
228+
server = new Server(options, compiler);
229+
230+
// eslint-disable-next-line no-undefined
231+
server.listen(port, undefined, () => {
232+
const info = server.server.address();
233+
234+
expect(info.address).toBe('127.0.0.1');
235+
expect(info.port).toBe(port);
236+
237+
server.close(done);
238+
});
239+
});
240+
241+
it('should work and using "port" from options and "port" from arguments', (done) => {
242+
const options = {
243+
port,
244+
};
245+
246+
server = new Server(options, compiler);
247+
248+
// eslint-disable-next-line no-undefined
249+
server.listen(undefined, '127.0.0.1', () => {
250+
const info = server.server.address();
251+
252+
expect(info.address).toBe('127.0.0.1');
253+
expect(info.port).toBe(port);
254+
255+
server.close(done);
256+
});
257+
});
258+
259+
it('should log warning when the "port" and "host" options from options different from arguments', (done) => {
260+
const options = {
261+
host: '127.0.0.2',
262+
port: '9999',
263+
};
264+
265+
server = new Server(compiler, options);
266+
267+
const loggerWarnSpy = jest.spyOn(server.logger, 'warn');
268+
269+
server.listen(port, '127.0.0.1', () => {
270+
const info = server.server.address();
271+
272+
expect(loggerWarnSpy).toHaveBeenNthCalledWith(
273+
1,
274+
'The "port" specified in options is different from the port passed as an argument. Will be used from arguments.'
275+
);
276+
expect(loggerWarnSpy).toHaveBeenNthCalledWith(
277+
2,
278+
'The "host" specified in options is different from the host passed as an argument. Will be used from arguments.'
279+
);
280+
expect(info.address).toBe('127.0.0.1');
281+
expect(info.port).toBe(port);
282+
283+
loggerWarnSpy.mockRestore();
284+
server.close(done);
285+
});
286+
});
287+
});
288+
164289
describe('checkHost', () => {
165290
let compiler;
166291
let server;

0 commit comments

Comments
 (0)