88 lines
2.9 KiB
JavaScript
88 lines
2.9 KiB
JavaScript
|
'use strict';
|
||
|
/* global self */
|
||
|
|
||
|
var url = require('url');
|
||
|
|
||
|
var getCurrentScriptSource = require('./getCurrentScriptSource');
|
||
|
|
||
|
function createSocketUrl(resourceQuery, currentLocation) {
|
||
|
var 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.
|
||
|
var 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) {
|
||
|
var auth = urlParts.auth,
|
||
|
query = urlParts.query;
|
||
|
var hostname = urlParts.hostname,
|
||
|
protocol = urlParts.protocol,
|
||
|
port = urlParts.port;
|
||
|
|
||
|
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
|
||
|
|
||
|
|
||
|
var sockHost = query.sockHost || hostname;
|
||
|
var sockPath = query.sockPath || '/sockjs-node';
|
||
|
var sockPort = query.sockPort || port;
|
||
|
|
||
|
if (sockPort === 'location') {
|
||
|
sockPort = loc.port;
|
||
|
}
|
||
|
|
||
|
return url.format({
|
||
|
protocol: protocol,
|
||
|
auth: 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;
|