3
3
/* global self */
4
4
5
5
const url = require ( 'url' ) ;
6
- const querystring = require ( 'querystring' ) ;
7
6
const getCurrentScriptSource = require ( './getCurrentScriptSource' ) ;
8
7
9
- function createSocketUrl ( resourceQuery ) {
8
+ function createSocketUrl ( resourceQuery , currentLocation ) {
10
9
let urlParts ;
11
10
12
11
if ( typeof resourceQuery === 'string' && resourceQuery !== '' ) {
13
12
// If this bundle is inlined, use the resource query to get the correct url.
14
- // strip leading `?` from query string
15
- urlParts = url . parse ( resourceQuery . substr ( 1 ) ) ;
13
+ // format is like `?http://0.0.0.0:8096&sockPort=8097&sockHost=localhost`
14
+ urlParts = url . parse (
15
+ resourceQuery
16
+ // strip leading `?` from query string to get a valid URL
17
+ . substr ( 1 )
18
+ // replace first `&` with `?` to have a valid query string
19
+ . replace ( '&' , '?' ) ,
20
+ true
21
+ ) ;
16
22
} else {
17
23
// Else, get the url from the <script> this file was called with.
18
24
const scriptHost = getCurrentScriptSource ( ) ;
19
- urlParts = url . parse ( scriptHost || '/' , false , true ) ;
25
+ urlParts = url . parse ( scriptHost || '/' , true , true ) ;
20
26
}
21
27
22
- if ( ! urlParts . port || urlParts . port === '0' ) {
23
- urlParts . port = self . location . port ;
28
+ // Use parameter to allow passing location in unit tests
29
+ if ( typeof currentLocation === 'string' && currentLocation !== '' ) {
30
+ currentLocation = url . parse ( currentLocation ) ;
31
+ } else {
32
+ currentLocation = self . location ;
24
33
}
25
34
26
- const { auth, path } = urlParts ;
27
- let { hostname, protocol } = urlParts ;
35
+ return getSocketUrl ( urlParts , currentLocation ) ;
36
+ }
37
+
38
+ /*
39
+ * Gets socket URL based on Script Source/Location
40
+ * (scriptSrc: URL, location: URL) -> URL
41
+ */
42
+ function getSocketUrl ( urlParts , loc ) {
43
+ const { auth, query } = urlParts ;
44
+ let { hostname, protocol, port } = urlParts ;
45
+
46
+ if ( ! port || port === '0' ) {
47
+ port = loc . port ;
48
+ }
28
49
29
50
// check ipv4 and ipv6 `all hostname`
30
51
// why do we need this check?
31
52
// hostname n/a for file protocol (example, when using electron, ionic)
32
53
// see: https://github.com/webpack/webpack-dev-server/pull/384
33
- const isAnyHostname =
54
+ if (
34
55
( hostname === '0.0.0.0' || hostname === '::' ) &&
35
- self . location . hostname &&
36
- // eslint-disable-next-line no-bitwise
37
- ! ! ~ self . location . protocol . indexOf ( 'http' ) ;
38
-
39
- if ( isAnyHostname ) {
40
- hostname = self . location . hostname ;
56
+ loc . hostname &&
57
+ loc . protocol . startsWith ( 'http' )
58
+ ) {
59
+ hostname = loc . hostname ;
41
60
}
42
61
43
62
// `hostname` can be empty when the script path is relative. In that case, specifying
@@ -47,27 +66,17 @@ function createSocketUrl(resourceQuery) {
47
66
if (
48
67
hostname &&
49
68
hostname !== '127.0.0.1' &&
50
- ( self . location . protocol === 'https:' || urlParts . hostname === '0.0.0.0' )
69
+ ( loc . protocol === 'https:' || urlParts . hostname === '0.0.0.0' )
51
70
) {
52
- protocol = self . location . protocol ;
71
+ protocol = loc . protocol ;
53
72
}
54
73
55
- // default values of the sock url if they are not provided
56
- let sockHost = hostname ;
57
- let sockPath = '/sockjs-node' ;
58
- let sockPort = urlParts . port ;
59
-
60
- // eslint-disable-next-line no-undefined
61
- const shouldParsePath = path !== null && path !== undefined && path !== '/' ;
62
- if ( shouldParsePath ) {
63
- const parsedQuery = querystring . parse ( path ) ;
64
- // all of these sock url params are optionally passed in through
65
- // resourceQuery, so we need to fall back to the default if
66
- // they are not provided
67
- sockHost = parsedQuery . sockHost || sockHost ;
68
- sockPath = parsedQuery . sockPath || sockPath ;
69
- sockPort = parsedQuery . sockPort || sockPort ;
70
- }
74
+ // all of these sock url params are optionally passed in through
75
+ // resourceQuery, so we need to fall back to the default if
76
+ // they are not provided
77
+ const sockHost = query . sockHost || hostname ;
78
+ const sockPath = query . sockPath || '/sockjs-node' ;
79
+ const sockPort = query . sockPort || port ;
71
80
72
81
return url . format ( {
73
82
protocol,
0 commit comments