You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

85 lines
2.9 KiB

4 years ago
  1. 'use strict';
  2. /* global self */
  3. var url = require('url');
  4. var querystring = require('querystring');
  5. var getCurrentScriptSource = require('./getCurrentScriptSource');
  6. function createSocketUrl(resourceQuery) {
  7. var urlParts;
  8. if (typeof resourceQuery === 'string' && resourceQuery !== '') {
  9. // If this bundle is inlined, use the resource query to get the correct url.
  10. urlParts = url.parse(resourceQuery.substr(1));
  11. } else {
  12. // Else, get the url from the <script> this file was called with.
  13. var scriptHost = getCurrentScriptSource();
  14. if (scriptHost) {
  15. // eslint-disable-next-line no-useless-escape
  16. scriptHost = scriptHost.replace(/\/[^\/]+$/, '');
  17. }
  18. urlParts = url.parse(scriptHost || '/', false, true);
  19. }
  20. if (!urlParts.port || urlParts.port === '0') {
  21. urlParts.port = self.location.port;
  22. }
  23. var _urlParts = urlParts,
  24. auth = _urlParts.auth,
  25. path = _urlParts.path;
  26. var _urlParts2 = urlParts,
  27. hostname = _urlParts2.hostname,
  28. protocol = _urlParts2.protocol; // check ipv4 and ipv6 `all hostname`
  29. // why do we need this check?
  30. // hostname n/a for file protocol (example, when using electron, ionic)
  31. // see: https://github.com/webpack/webpack-dev-server/pull/384
  32. var isAnyHostname = (hostname === '0.0.0.0' || hostname === '::') && self.location.hostname && // eslint-disable-next-line no-bitwise
  33. !!~self.location.protocol.indexOf('http');
  34. if (isAnyHostname) {
  35. hostname = self.location.hostname;
  36. } // `hostname` can be empty when the script path is relative. In that case, specifying
  37. // a protocol would result in an invalid URL.
  38. // When https is used in the app, secure websockets are always necessary
  39. // because the browser doesn't accept non-secure websockets.
  40. if (hostname && (self.location.protocol === 'https:' || urlParts.hostname === '0.0.0.0')) {
  41. protocol = self.location.protocol;
  42. } // default values of the sock url if they are not provided
  43. var sockHost = hostname;
  44. var sockPath = '/sockjs-node';
  45. var sockPort = urlParts.port; // eslint-disable-next-line no-undefined
  46. var shouldParsePath = path !== null && path !== undefined && path !== '/';
  47. if (shouldParsePath) {
  48. var parsedQuery = querystring.parse(path); // all of these sock url params are optionally passed in through
  49. // resourceQuery, so we need to fall back to the default if
  50. // they are not provided
  51. sockHost = parsedQuery.sockHost || sockHost;
  52. sockPath = parsedQuery.sockPath || sockPath;
  53. sockPort = parsedQuery.sockPort || sockPort;
  54. }
  55. return url.format({
  56. protocol: protocol,
  57. auth: auth,
  58. hostname: sockHost,
  59. port: sockPort,
  60. // If sockPath is provided it'll be passed in via the resourceQuery as a
  61. // query param so it has to be parsed out of the querystring in order for the
  62. // client to open the socket to the correct location.
  63. pathname: sockPath
  64. });
  65. }
  66. module.exports = createSocketUrl;