network.js 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.NET_DEFAULT_TIMEOUT = void 0;
  6. exports.constructURLBasedOnBaseURL = constructURLBasedOnBaseURL;
  7. exports.createHttpServer = createHttpServer;
  8. exports.createHttpsServer = createHttpsServer;
  9. exports.fetchData = fetchData;
  10. exports.httpRequest = httpRequest;
  11. exports.urlMatches = urlMatches;
  12. exports.urlMatchesEqual = urlMatchesEqual;
  13. var _http = _interopRequireDefault(require("http"));
  14. var _https = _interopRequireDefault(require("https"));
  15. var _utilsBundle = require("../utilsBundle");
  16. var _url = _interopRequireDefault(require("url"));
  17. var _rtti = require("./rtti");
  18. var _glob = require("./glob");
  19. var _happyEyeballs = require("./happy-eyeballs");
  20. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  21. /**
  22. * Copyright (c) Microsoft Corporation.
  23. *
  24. * Licensed under the Apache License, Version 2.0 (the "License");
  25. * you may not use this file except in compliance with the License.
  26. * You may obtain a copy of the License at
  27. *
  28. * http://www.apache.org/licenses/LICENSE-2.0
  29. *
  30. * Unless required by applicable law or agreed to in writing, software
  31. * distributed under the License is distributed on an "AS IS" BASIS,
  32. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  33. * See the License for the specific language governing permissions and
  34. * limitations under the License.
  35. */
  36. const NET_DEFAULT_TIMEOUT = exports.NET_DEFAULT_TIMEOUT = 30_000;
  37. function httpRequest(params, onResponse, onError) {
  38. var _params$timeout;
  39. const parsedUrl = _url.default.parse(params.url);
  40. let options = {
  41. ...parsedUrl,
  42. agent: parsedUrl.protocol === 'https:' ? _happyEyeballs.httpsHappyEyeballsAgent : _happyEyeballs.httpHappyEyeballsAgent,
  43. method: params.method || 'GET',
  44. headers: params.headers
  45. };
  46. if (params.rejectUnauthorized !== undefined) options.rejectUnauthorized = params.rejectUnauthorized;
  47. const timeout = (_params$timeout = params.timeout) !== null && _params$timeout !== void 0 ? _params$timeout : NET_DEFAULT_TIMEOUT;
  48. const proxyURL = (0, _utilsBundle.getProxyForUrl)(params.url);
  49. if (proxyURL) {
  50. const parsedProxyURL = _url.default.parse(proxyURL);
  51. if (params.url.startsWith('http:')) {
  52. options = {
  53. path: parsedUrl.href,
  54. host: parsedProxyURL.hostname,
  55. port: parsedProxyURL.port,
  56. headers: options.headers,
  57. method: options.method
  58. };
  59. } else {
  60. parsedProxyURL.secureProxy = parsedProxyURL.protocol === 'https:';
  61. options.agent = new _utilsBundle.HttpsProxyAgent(parsedProxyURL);
  62. options.rejectUnauthorized = false;
  63. }
  64. }
  65. const requestCallback = res => {
  66. const statusCode = res.statusCode || 0;
  67. if (statusCode >= 300 && statusCode < 400 && res.headers.location) httpRequest({
  68. ...params,
  69. url: new URL(res.headers.location, params.url).toString()
  70. }, onResponse, onError);else onResponse(res);
  71. };
  72. const request = options.protocol === 'https:' ? _https.default.request(options, requestCallback) : _http.default.request(options, requestCallback);
  73. request.on('error', onError);
  74. if (timeout !== undefined) {
  75. const rejectOnTimeout = () => {
  76. onError(new Error(`Request to ${params.url} timed out after ${timeout}ms`));
  77. request.abort();
  78. };
  79. if (timeout <= 0) {
  80. rejectOnTimeout();
  81. return;
  82. }
  83. request.setTimeout(timeout, rejectOnTimeout);
  84. }
  85. request.end(params.data);
  86. }
  87. function fetchData(params, onError) {
  88. return new Promise((resolve, reject) => {
  89. httpRequest(params, async response => {
  90. if (response.statusCode !== 200) {
  91. const error = onError ? await onError(params, response) : new Error(`fetch failed: server returned code ${response.statusCode}. URL: ${params.url}`);
  92. reject(error);
  93. return;
  94. }
  95. let body = '';
  96. response.on('data', chunk => body += chunk);
  97. response.on('error', error => reject(error));
  98. response.on('end', () => resolve(body));
  99. }, reject);
  100. });
  101. }
  102. function urlMatchesEqual(match1, match2) {
  103. if ((0, _rtti.isRegExp)(match1) && (0, _rtti.isRegExp)(match2)) return match1.source === match2.source && match1.flags === match2.flags;
  104. return match1 === match2;
  105. }
  106. function urlMatches(baseURL, urlString, match) {
  107. if (match === undefined || match === '') return true;
  108. if ((0, _rtti.isString)(match) && !match.startsWith('*')) match = constructURLBasedOnBaseURL(baseURL, match);
  109. if ((0, _rtti.isString)(match)) match = (0, _glob.globToRegex)(match);
  110. if ((0, _rtti.isRegExp)(match)) return match.test(urlString);
  111. if (typeof match === 'string' && match === urlString) return true;
  112. const url = parsedURL(urlString);
  113. if (!url) return false;
  114. if (typeof match === 'string') return url.pathname === match;
  115. if (typeof match !== 'function') throw new Error('url parameter should be string, RegExp or function');
  116. return match(url);
  117. }
  118. function parsedURL(url) {
  119. try {
  120. return new URL(url);
  121. } catch (e) {
  122. return null;
  123. }
  124. }
  125. function constructURLBasedOnBaseURL(baseURL, givenURL) {
  126. try {
  127. return new URL(givenURL, baseURL).toString();
  128. } catch (e) {
  129. return givenURL;
  130. }
  131. }
  132. function createHttpServer(...args) {
  133. const server = _http.default.createServer(...args);
  134. decorateServer(server);
  135. return server;
  136. }
  137. function createHttpsServer(...args) {
  138. const server = _https.default.createServer(...args);
  139. decorateServer(server);
  140. return server;
  141. }
  142. function decorateServer(server) {
  143. const sockets = new Set();
  144. server.on('connection', socket => {
  145. sockets.add(socket);
  146. socket.once('close', () => sockets.delete(socket));
  147. });
  148. const close = server.close;
  149. server.close = callback => {
  150. for (const socket of sockets) socket.destroy();
  151. sockets.clear();
  152. return close.call(server, callback);
  153. };
  154. }