121 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			121 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
/**
 | 
						|
 * @param {{ protocol?: string, auth?: string, hostname?: string, port?: string, pathname?: string, search?: string, hash?: string, slashes?: boolean }} objURL
 | 
						|
 * @returns {string}
 | 
						|
 */
 | 
						|
function format(objURL) {
 | 
						|
  var protocol = objURL.protocol || "";
 | 
						|
  if (protocol && protocol.substr(-1) !== ":") {
 | 
						|
    protocol += ":";
 | 
						|
  }
 | 
						|
  var auth = objURL.auth || "";
 | 
						|
  if (auth) {
 | 
						|
    auth = encodeURIComponent(auth);
 | 
						|
    auth = auth.replace(/%3A/i, ":");
 | 
						|
    auth += "@";
 | 
						|
  }
 | 
						|
  var host = "";
 | 
						|
  if (objURL.hostname) {
 | 
						|
    host = auth + (objURL.hostname.indexOf(":") === -1 ? objURL.hostname : "[".concat(objURL.hostname, "]"));
 | 
						|
    if (objURL.port) {
 | 
						|
      host += ":".concat(objURL.port);
 | 
						|
    }
 | 
						|
  }
 | 
						|
  var pathname = objURL.pathname || "";
 | 
						|
  if (objURL.slashes) {
 | 
						|
    host = "//".concat(host || "");
 | 
						|
    if (pathname && pathname.charAt(0) !== "/") {
 | 
						|
      pathname = "/".concat(pathname);
 | 
						|
    }
 | 
						|
  } else if (!host) {
 | 
						|
    host = "";
 | 
						|
  }
 | 
						|
  var search = objURL.search || "";
 | 
						|
  if (search && search.charAt(0) !== "?") {
 | 
						|
    search = "?".concat(search);
 | 
						|
  }
 | 
						|
  var hash = objURL.hash || "";
 | 
						|
  if (hash && hash.charAt(0) !== "#") {
 | 
						|
    hash = "#".concat(hash);
 | 
						|
  }
 | 
						|
  pathname = pathname.replace(/[?#]/g,
 | 
						|
  /**
 | 
						|
   * @param {string} match
 | 
						|
   * @returns {string}
 | 
						|
   */
 | 
						|
  function (match) {
 | 
						|
    return encodeURIComponent(match);
 | 
						|
  });
 | 
						|
  search = search.replace("#", "%23");
 | 
						|
  return "".concat(protocol).concat(host).concat(pathname).concat(search).concat(hash);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * @param {URL & { fromCurrentScript?: boolean }} parsedURL
 | 
						|
 * @returns {string}
 | 
						|
 */
 | 
						|
function createSocketURL(parsedURL) {
 | 
						|
  var hostname = parsedURL.hostname;
 | 
						|
 | 
						|
  // Node.js module parses it as `::`
 | 
						|
  // `new URL(urlString, [baseURLString])` parses it as '[::]'
 | 
						|
  var isInAddrAny = hostname === "0.0.0.0" || hostname === "::" || 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 (isInAddrAny && self.location.hostname && self.location.protocol.indexOf("http") === 0) {
 | 
						|
    hostname = self.location.hostname;
 | 
						|
  }
 | 
						|
  var socketURLProtocol = parsedURL.protocol || self.location.protocol;
 | 
						|
 | 
						|
  // When https is used in the app, secure web sockets are always necessary because the browser doesn't accept non-secure web sockets.
 | 
						|
  if (socketURLProtocol === "auto:" || hostname && isInAddrAny && self.location.protocol === "https:") {
 | 
						|
    socketURLProtocol = self.location.protocol;
 | 
						|
  }
 | 
						|
  socketURLProtocol = socketURLProtocol.replace(/^(?:http|.+-extension|file)/i, "ws");
 | 
						|
  var socketURLAuth = "";
 | 
						|
 | 
						|
  // `new URL(urlString, [baseURLstring])` doesn't have `auth` property
 | 
						|
  // Parse authentication credentials in case we need them
 | 
						|
  if (parsedURL.username) {
 | 
						|
    socketURLAuth = parsedURL.username;
 | 
						|
 | 
						|
    // Since HTTP basic authentication does not allow empty username,
 | 
						|
    // we only include password if the username is not empty.
 | 
						|
    if (parsedURL.password) {
 | 
						|
      // Result: <username>:<password>
 | 
						|
      socketURLAuth = socketURLAuth.concat(":", parsedURL.password);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  // In case the host is a raw IPv6 address, it can be enclosed in
 | 
						|
  // the brackets as the brackets are needed in the final URL string.
 | 
						|
  // Need to remove those as url.format blindly adds its own set of brackets
 | 
						|
  // if the host string contains colons. That would lead to non-working
 | 
						|
  // double brackets (e.g. [[::]]) host
 | 
						|
  //
 | 
						|
  // All of these web socket url params are optionally passed in through resourceQuery,
 | 
						|
  // so we need to fall back to the default if they are not provided
 | 
						|
  var socketURLHostname = (hostname || self.location.hostname || "localhost").replace(/^\[(.*)\]$/, "$1");
 | 
						|
  var socketURLPort = parsedURL.port;
 | 
						|
  if (!socketURLPort || socketURLPort === "0") {
 | 
						|
    socketURLPort = self.location.port;
 | 
						|
  }
 | 
						|
 | 
						|
  // If path 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.
 | 
						|
  var socketURLPathname = "/ws";
 | 
						|
  if (parsedURL.pathname && !parsedURL.fromCurrentScript) {
 | 
						|
    socketURLPathname = parsedURL.pathname;
 | 
						|
  }
 | 
						|
  return format({
 | 
						|
    protocol: socketURLProtocol,
 | 
						|
    auth: socketURLAuth,
 | 
						|
    hostname: socketURLHostname,
 | 
						|
    port: socketURLPort,
 | 
						|
    pathname: socketURLPathname,
 | 
						|
    slashes: true
 | 
						|
  });
 | 
						|
}
 | 
						|
export default createSocketURL; |