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; | 
