-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
/
Copy pathcreateSocketUrl.js
97 lines (83 loc) · 2.91 KB
/
createSocketUrl.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
'use strict';
/* global self */
const url = require('url');
const getCurrentScriptSource = require('./getCurrentScriptSource');
function createSocketUrl(resourceQuery, currentLocation) {
let urlParts;
if (typeof resourceQuery === 'string' && resourceQuery !== '') {
// If this bundle is inlined, use the resource query to get the correct url.
// format is like `?http://0.0.0.0:8096&sockPort=8097&sockHost=localhost`
urlParts = url.parse(
resourceQuery
// strip leading `?` from query string to get a valid URL
.substr(1)
// replace first `&` with `?` to have a valid query string
.replace('&', '?'),
true
);
} else {
// Else, get the url from the <script> this file was called with.
const scriptHost = getCurrentScriptSource();
urlParts = url.parse(scriptHost || '/', true, true);
}
// Use parameter to allow passing location in unit tests
if (typeof currentLocation === 'string' && currentLocation !== '') {
currentLocation = url.parse(currentLocation);
} else {
currentLocation = self.location;
}
return getSocketUrl(urlParts, currentLocation);
}
/*
* Gets socket URL based on Script Source/Location
* (scriptSrc: URL, location: URL) -> URL
*/
function getSocketUrl(urlParts, loc) {
const { auth, query } = urlParts;
let { hostname, protocol, port } = urlParts;
if (!port || port === '0') {
port = loc.port;
}
// check ipv4 and ipv6 `all hostname`
// why do we need this check?
// hostname n/a for file protocol (example, when using electron, ionic)
// see: https://github.com/webpack/webpack-dev-server/pull/384
if (
(hostname === '0.0.0.0' || hostname === '::') &&
loc.hostname &&
loc.protocol.indexOf('http') === 0
) {
hostname = loc.hostname;
}
// `hostname` can be empty when the script path is relative. In that case, specifying
// a protocol would result in an invalid URL.
// When https is used in the app, secure websockets are always necessary
// because the browser doesn't accept non-secure websockets.
if (
hostname &&
hostname !== '127.0.0.1' &&
(loc.protocol === 'https:' || urlParts.hostname === '0.0.0.0')
) {
protocol = loc.protocol;
}
// all of these sock url params are optionally passed in through
// resourceQuery, so we need to fall back to the default if
// they are not provided
const sockHost = query.sockHost || hostname;
const sockPath = query.sockPath || '/sockjs-node';
let sockPort = query.sockPort || port;
if (sockPort === 'location') {
sockPort = loc.port;
}
return url.format({
protocol,
auth,
hostname: sockHost,
port: sockPort,
// If sockPath is provided it'll be passed in via the resourceQuery as a
// query param so it has to be parsed out of the querystring in order for the
// client to open the socket to the correct location.
pathname: sockPath,
});
}
module.exports = createSocketUrl;