@@ -1469,6 +1469,23 @@ class Server {
14691469 }
14701470 }
14711471
1472+ /**
1473+ * @returns { { isColorSupported: () => boolean, colors: import("webpack").Colors } } colors support
1474+ */
1475+ #getColors( ) {
1476+ const compilerOptions =
1477+ /** @type {MultiCompiler } */
1478+ ( this . compiler ) . compilers
1479+ ? /** @type {MultiCompiler } */ ( this . compiler ) . compilers [ 0 ] . webpack
1480+ : /** @type {Compiler } */ ( this . compiler ) . webpack ;
1481+
1482+ const colors = compilerOptions . cli . createColors ( {
1483+ useColor : compilerOptions . cli . isColorSupported ( ) ,
1484+ } ) ;
1485+
1486+ return { isColorSupported : compilerOptions . cli . isColorSupported , colors } ;
1487+ }
1488+
14721489 /**
14731490 * @private
14741491 * @returns {string } client transport
@@ -2687,7 +2704,10 @@ class Server {
26872704 * @returns {Promise<void> }
26882705 */
26892706 async logStatus ( ) {
2690- const { cyan, isColorSupported, red } = require ( "colorette" ) ;
2707+ const {
2708+ isColorSupported,
2709+ colors : { cyan, red } ,
2710+ } = this . #getColors( ) ;
26912711
26922712 /**
26932713 * @param {Compiler["options"] } compilerOptions compiler options
@@ -2708,7 +2728,7 @@ class Server {
27082728 /** @type {boolean } */
27092729 ( /** @type {StatsOptions } */ ( compilerOptions . stats ) . colors ) ;
27102730 } else {
2711- colorsEnabled = isColorSupported ;
2731+ colorsEnabled = isColorSupported ( ) ;
27122732 }
27132733
27142734 return colorsEnabled ;
@@ -3002,6 +3022,32 @@ class Server {
30023022 return false ;
30033023 }
30043024
3025+ /**
3026+ * Extracts and normalizes the hostname from a header, removing brackets for IPv6.
3027+ * @param {string } header header value
3028+ * @returns {string|null } hostname or null
3029+ */
3030+ #parseHostnameFromHeader = function ( header ) {
3031+ if ( ! header ) return null ;
3032+ try {
3033+ // If the header does not have a scheme, prepend // so URL can parse it
3034+ const parseUrl = new URL (
3035+ / ^ ( .+ : ) ? \/ \/ / . test ( header ) ? header : `//${ header } ` ,
3036+ "http://localhost/" ,
3037+ ) ;
3038+
3039+ let hostname = parseUrl . hostname ;
3040+ // Normalize IPv6: remove brackets if present
3041+ if ( hostname . startsWith ( "[" ) && hostname . endsWith ( "]" ) ) {
3042+ hostname = hostname . slice ( 1 , - 1 ) ;
3043+ }
3044+
3045+ return hostname ;
3046+ } catch {
3047+ return null ;
3048+ }
3049+ } ;
3050+
30053051 /**
30063052 * @private
30073053 * @param {{ [key: string]: string | undefined } } headers headers
@@ -3026,15 +3072,7 @@ class Server {
30263072 return true ;
30273073 }
30283074
3029- // use the node url-parser to retrieve the hostname from the host-header.
3030- // TODO resolve me in the next major release
3031- // eslint-disable-next-line n/no-deprecated-api
3032- const { hostname } = url . parse (
3033- // if header doesn't have scheme, add // for parsing.
3034- / ^ ( .+ : ) ? \/ \/ / . test ( header ) ? header : `//${ header } ` ,
3035- false ,
3036- true ,
3037- ) ;
3075+ const hostname = this . #parseHostnameFromHeader( header ) ;
30383076
30393077 if ( hostname === null ) {
30403078 return false ;
@@ -3048,8 +3086,7 @@ class Server {
30483086 // A note on IPv6 addresses:
30493087 // header will always contain the brackets denoting
30503088 // an IPv6-address in URLs,
3051- // these are removed from the hostname in url.parse(),
3052- // so we have the pure IPv6-address in hostname.
3089+ // these aren't removed from the hostname in new URL(),
30533090 // For convenience, always allow localhost (hostname === 'localhost')
30543091 // and its subdomains (hostname.endsWith(".localhost")).
30553092 // allow hostname of listening address (hostname === this.options.host)
@@ -3084,9 +3121,7 @@ class Server {
30843121 return true ;
30853122 }
30863123
3087- // TODO resolve me in the next major release
3088- // eslint-disable-next-line n/no-deprecated-api
3089- const origin = url . parse ( originHeader , false , true ) . hostname ;
3124+ const origin = this . #parseHostnameFromHeader( originHeader ) ;
30903125
30913126 if ( origin === null ) {
30923127 return false ;
@@ -3106,13 +3141,7 @@ class Server {
31063141 return true ;
31073142 }
31083143
3109- // eslint-disable-next-line n/no-deprecated-api
3110- const host = url . parse (
3111- // if hostHeader doesn't have scheme, add // for parsing.
3112- / ^ ( .+ : ) ? \/ \/ / . test ( hostHeader ) ? hostHeader : `//${ hostHeader } ` ,
3113- false ,
3114- true ,
3115- ) . hostname ;
3144+ const host = this . #parseHostnameFromHeader( hostHeader ) ;
31163145
31173146 if ( host === null ) {
31183147 return false ;
0 commit comments