Skip to content

Commit f362665

Browse files
feat: improve output for IPv4 and IPv6 (#3092)
1 parent 2496110 commit f362665

File tree

8 files changed

+2104
-358
lines changed

8 files changed

+2104
-358
lines changed

lib/Server.js

+70-21
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ const path = require('path');
55
const url = require('url');
66
const http = require('http');
77
const https = require('https');
8-
const ip = require('ip');
8+
const ipaddr = require('ipaddr.js');
99
const internalIp = require('internal-ip');
1010
const killable = require('killable');
1111
const chokidar = require('chokidar');
@@ -592,33 +592,76 @@ class Server {
592592
const prettyPrintUrl = (newHostname) =>
593593
url.format({ protocol, hostname: newHostname, port, pathname: '/' });
594594

595-
let prettyHostname;
596-
let lanUrlForTerminal;
595+
let localhostForTerminal;
596+
let networkUrlForTerminalIPv4;
597+
let networkUrlForTerminalIPv6;
597598

598-
if (hostname === '0.0.0.0' || ip.isLoopback(hostname)) {
599-
prettyHostname = 'localhost';
599+
const parsedIP = ipaddr.parse(hostname);
600600

601-
const localIP =
602-
hostname === '::' ? internalIp.v6.sync() : internalIp.v4.sync();
601+
if (parsedIP.range() === 'unspecified') {
602+
localhostForTerminal = prettyPrintUrl('localhost');
603603

604-
if (localIP) {
605-
lanUrlForTerminal = prettyPrintUrl(localIP);
604+
const networkIPv4 = internalIp.v4.sync();
605+
606+
if (networkIPv4) {
607+
networkUrlForTerminalIPv4 = prettyPrintUrl(networkIPv4);
608+
}
609+
610+
if (hostname === '::') {
611+
const networkIPv6 = internalIp.v6.sync();
612+
613+
if (networkIPv6) {
614+
networkUrlForTerminalIPv6 = prettyPrintUrl(networkIPv6);
615+
}
606616
}
607617
} else {
608-
prettyHostname = hostname;
609-
}
618+
if (parsedIP.kind() === 'ipv6') {
619+
if (parsedIP.isIPv4MappedAddress()) {
620+
networkUrlForTerminalIPv4 = prettyPrintUrl(
621+
parsedIP.toIPv4Address().toString()
622+
);
623+
}
624+
} else {
625+
networkUrlForTerminalIPv4 = prettyPrintUrl(hostname);
626+
}
610627

611-
const localUrlForTerminal = prettyPrintUrl(prettyHostname);
628+
if (parsedIP.kind() === 'ipv6') {
629+
networkUrlForTerminalIPv6 = prettyPrintUrl(hostname);
630+
}
631+
}
612632

613-
if (lanUrlForTerminal) {
633+
if (localhostForTerminal) {
614634
this.logger.info('Project is running at:');
615-
this.logger.info(`Local: ${colors.info(useColor, localUrlForTerminal)}`);
616-
this.logger.info(
617-
`On Your Network: ${colors.info(useColor, lanUrlForTerminal)}`
618-
);
635+
this.logger.info(`Local: ${colors.info(useColor, localhostForTerminal)}`);
636+
637+
const networkUrlsForTerminal = []
638+
.concat(
639+
networkUrlForTerminalIPv4
640+
? [`${colors.info(useColor, networkUrlForTerminalIPv4)} (IPv4)`]
641+
: []
642+
)
643+
.concat(
644+
networkUrlForTerminalIPv6
645+
? [`${colors.info(useColor, networkUrlForTerminalIPv6)} (IPv6)`]
646+
: []
647+
);
648+
649+
this.logger.info(`On Your Network: ${networkUrlsForTerminal.join(', ')}`);
619650
} else {
651+
const networkUrlsForTerminal = []
652+
.concat(
653+
networkUrlForTerminalIPv4
654+
? [`${colors.info(useColor, networkUrlForTerminalIPv4)} (IPv4)`]
655+
: []
656+
)
657+
.concat(
658+
networkUrlForTerminalIPv6
659+
? [`${colors.info(useColor, networkUrlForTerminalIPv6)} (IPv6)`]
660+
: []
661+
);
662+
620663
this.logger.info(
621-
`Project is running at ${colors.info(useColor, localUrlForTerminal)}`
664+
`Project is running at ${networkUrlsForTerminal.join(', ')}`
622665
);
623666
}
624667

@@ -663,7 +706,12 @@ class Server {
663706
}
664707

665708
if (this.options.open || this.options.openPage) {
666-
runOpen(localUrlForTerminal, this.options, this.logger);
709+
const uri =
710+
localhostForTerminal ||
711+
networkUrlForTerminalIPv4 ||
712+
networkUrlForTerminalIPv6;
713+
714+
runOpen(uri, this.options, this.logger);
667715
}
668716
}
669717

@@ -804,6 +852,7 @@ class Server {
804852
false,
805853
true
806854
).hostname;
855+
807856
// always allow requests with explicit IPv4 or IPv6-address.
808857
// A note on IPv6 addresses:
809858
// hostHeader will always contain the brackets denoting
@@ -813,8 +862,8 @@ class Server {
813862
// always allow localhost host, for convenience (hostname === 'localhost')
814863
// allow hostname of listening address (hostname === this.hostname)
815864
const isValidHostname =
816-
ip.isV4Format(hostname) ||
817-
ip.isV6Format(hostname) ||
865+
ipaddr.IPv4.isValid(hostname) ||
866+
ipaddr.IPv6.isValid(hostname) ||
818867
hostname === 'localhost' ||
819868
hostname === this.hostname;
820869

0 commit comments

Comments
 (0)