@@ -6,7 +6,7 @@ const getCurrentScriptSource = require('./getCurrentScriptSource.js');
66 * @property {string } hostname
77 * @property {string } [protocol]
88 * @property {string } pathname
9- * @property {string } port
9+ * @property {string } [ port]
1010 */
1111
1212/**
@@ -21,92 +21,103 @@ function getSocketUrlParts(resourceQuery, metadata) {
2121 metadata = { } ;
2222 }
2323
24- const scriptSource = getCurrentScriptSource ( ) ;
25-
26- let url = { } ;
27- try {
28- // The placeholder `baseURL` with `window.location.href`,
29- // is to allow parsing of path-relative or protocol-relative URLs,
30- // and will have no effect if `scriptSource` is a fully valid URL.
31- url = new URL ( scriptSource , window . location . href ) ;
32- } catch ( e ) {
33- // URL parsing failed, do nothing.
34- // We will still proceed to see if we can recover using `resourceQuery`
35- }
36-
37- /** @type {string | undefined } */
38- let auth ;
39- /** @type {string | undefined } */
40- let hostname = url . hostname ;
41- /** @type {string | undefined } */
42- let protocol = url . protocol ;
43- /** @type {string | undefined } */
44- let port = url . port ;
45-
46- // This is hard-coded in WDS v3
47- let pathname = '/sockjs-node' ;
48- if ( metadata . version === 4 ) {
49- // This is hard-coded in WDS v4
50- pathname = '/ws' ;
51- }
52-
53- // Parse authentication credentials in case we need them
54- if ( url . username ) {
55- // Since HTTP basic authentication does not allow empty username,
56- // we only include password if the username is not empty.
57- // Result: <username> or <username>:<password>
58- auth = url . username ;
59- if ( url . password ) {
60- auth += ':' + url . password ;
61- }
62- }
24+ /** @type {SocketUrlParts } */
25+ let urlParts = { } ;
6326
6427 // If the resource query is available,
65- // parse it and overwrite everything we received from the script host.
66- const parsedQuery = { } ;
28+ // parse it and ignore everything we received from the script host.
6729 if ( resourceQuery ) {
30+ const parsedQuery = { } ;
6831 const searchParams = new URLSearchParams ( resourceQuery . slice ( 1 ) ) ;
6932 searchParams . forEach ( function ( value , key ) {
7033 parsedQuery [ key ] = value ;
7134 } ) ;
72- }
7335
74- hostname = parsedQuery . sockHost || hostname ;
75- pathname = parsedQuery . sockPath || pathname ;
76- port = parsedQuery . sockPort || port ;
36+ urlParts . hostname = parsedQuery . sockHost ;
37+ urlParts . pathname = parsedQuery . sockPath ;
38+ urlParts . port = parsedQuery . sockPort ;
39+
40+ // Make sure the protocol from resource query has a trailing colon
41+ if ( parsedQuery . sockProtocol ) {
42+ urlParts . protocol = parsedQuery . sockProtocol + ':' ;
43+ }
44+ } else {
45+ const scriptSource = getCurrentScriptSource ( ) ;
46+
47+ let url = { } ;
48+ try {
49+ // The placeholder `baseURL` with `window.location.href`,
50+ // is to allow parsing of path-relative or protocol-relative URLs,
51+ // and will have no effect if `scriptSource` is a fully valid URL.
52+ url = new URL ( scriptSource , window . location . href ) ;
53+ } catch ( e ) {
54+ // URL parsing failed, do nothing.
55+ // We will still proceed to see if we can recover using `resourceQuery`
56+ }
7757
78- // Make sure the protocol from resource query has a trailing colon
79- if ( parsedQuery . sockProtocol ) {
80- protocol = parsedQuery . sockProtocol + ':' ;
58+ // Parse authentication credentials in case we need them
59+ if ( url . username ) {
60+ // Since HTTP basic authentication does not allow empty username,
61+ // we only include password if the username is not empty.
62+ // Result: <username> or <username>:<password>
63+ urlParts . auth = url . username ;
64+ if ( url . password ) {
65+ urlParts . auth += ':' + url . password ;
66+ }
67+ }
68+
69+ // `file://` URLs has `'null'` origin
70+ if ( url . origin !== 'null' ) {
71+ urlParts . hostname = url . hostname ;
72+ }
73+
74+ urlParts . protocol = url . protocol ;
75+ urlParts . port = url . port ;
8176 }
8277
83- // Check for IPv4 and IPv6 host addresses that corresponds to any/empty.
78+ if ( ! urlParts . pathname ) {
79+ if ( metadata . version === 4 ) {
80+ // This is hard-coded in WDS v4
81+ urlParts . pathname = '/ws' ;
82+ } else {
83+ // This is hard-coded in WDS v3
84+ urlParts . pathname = '/sockjs-node' ;
85+ }
86+ }
87+
88+ // Check for IPv4 and IPv6 host addresses that correspond to any/empty.
8489 // This is important because `hostname` can be empty for some hosts,
8590 // such as 'about:blank' or 'file://' URLs.
86- const isEmptyHostname = hostname === '0.0.0.0' || hostname === '[::]' || ! hostname ;
91+ const isEmptyHostname =
92+ urlParts . hostname === '0.0.0.0' || urlParts . hostname === '[::]' || ! urlParts . hostname ;
8793 // We only re-assign the hostname if it is empty,
8894 // and if we are using HTTP/HTTPS protocols.
8995 if (
9096 isEmptyHostname &&
9197 window . location . hostname &&
92- window . location . protocol . indexOf ( 'http' ) !== - 1
98+ window . location . protocol . indexOf ( 'http' ) === 0
9399 ) {
94- hostname = window . location . hostname ;
100+ urlParts . hostname = window . location . hostname ;
95101 }
96102
97- // We only re-assign `protocol` when `hostname` is available and is empty,
103+ // We only re-assign `protocol` when `protocol` is unavailable,
104+ // or if `hostname` is available and is empty,
98105 // since otherwise we risk creating an invalid URL.
99106 // We also do this when 'https' is used as it mandates the use of secure sockets.
100- if ( hostname && ( isEmptyHostname || window . location . protocol === 'https:' ) ) {
101- protocol = window . location . protocol ;
107+ if (
108+ ! urlParts . protocol ||
109+ ( urlParts . hostname && ( isEmptyHostname || window . location . protocol === 'https:' ) )
110+ ) {
111+ urlParts . protocol = window . location . protocol ;
102112 }
103113
104114 // We only re-assign port when it is not available
105- if ( ! port ) {
106- port = window . location . port ;
115+ if ( ! urlParts . port ) {
116+ urlParts . port = window . location . port ;
107117 }
108118
109- if ( ! hostname || ! pathname || ! port ) {
119+ if ( ! urlParts . hostname || ! urlParts . pathname ) {
120+ console . log ( urlParts ) ;
110121 throw new Error (
111122 [
112123 '[React Refresh] Failed to get an URL for the socket connection.' ,
@@ -118,11 +129,11 @@ function getSocketUrlParts(resourceQuery, metadata) {
118129 }
119130
120131 return {
121- auth : auth ,
122- hostname : hostname ,
123- pathname : pathname ,
124- protocol : protocol ,
125- port : port ,
132+ auth : urlParts . auth ,
133+ hostname : urlParts . hostname ,
134+ pathname : urlParts . pathname ,
135+ protocol : urlParts . protocol ,
136+ port : urlParts . port || undefined ,
126137 } ;
127138}
128139
0 commit comments