multipleRangeDownloader.js 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.executeTasks = executeTasks;
  6. exports._executeTasks = _executeTasks;
  7. exports.checkIsRangesSupported = checkIsRangesSupported;
  8. function _builderUtilRuntime() {
  9. const data = require("builder-util-runtime");
  10. _builderUtilRuntime = function () {
  11. return data;
  12. };
  13. return data;
  14. }
  15. function _DataSplitter() {
  16. const data = require("./DataSplitter");
  17. _DataSplitter = function () {
  18. return data;
  19. };
  20. return data;
  21. }
  22. function _downloadPlanBuilder() {
  23. const data = require("./downloadPlanBuilder");
  24. _downloadPlanBuilder = function () {
  25. return data;
  26. };
  27. return data;
  28. }
  29. function executeTasks(differentialDownloader, tasks, out, oldFileFd, reject) {
  30. const w = taskOffset => {
  31. if (taskOffset >= tasks.length) {
  32. if (differentialDownloader.fileMetadataBuffer != null) {
  33. out.write(differentialDownloader.fileMetadataBuffer);
  34. }
  35. out.end();
  36. return;
  37. }
  38. const nextOffset = taskOffset + (differentialDownloader.options.useMultipleRangeRequest === false ? 1 : 1000);
  39. _executeTasks(differentialDownloader, {
  40. tasks,
  41. start: taskOffset,
  42. end: Math.min(tasks.length, nextOffset),
  43. oldFileFd
  44. }, out, () => w(nextOffset), reject);
  45. };
  46. return w;
  47. }
  48. function _executeTasks(differentialDownloader, options, out, resolve, reject) {
  49. let ranges = "bytes=";
  50. let partCount = 0;
  51. const partIndexToTaskIndex = new Map();
  52. const partIndexToLength = [];
  53. for (let i = options.start; i < options.end; i++) {
  54. const task = options.tasks[i];
  55. if (task.kind === _downloadPlanBuilder().OperationKind.DOWNLOAD) {
  56. ranges += `${task.start}-${task.end - 1}, `;
  57. partIndexToTaskIndex.set(partCount, i);
  58. partCount++;
  59. partIndexToLength.push(task.end - task.start);
  60. }
  61. }
  62. if (partCount <= 1) {
  63. // the only remote range - copy
  64. const w = index => {
  65. if (index >= options.end) {
  66. resolve();
  67. return;
  68. }
  69. const task = options.tasks[index++];
  70. if (task.kind === _downloadPlanBuilder().OperationKind.COPY) {
  71. (0, _DataSplitter().copyData)(task, out, options.oldFileFd, reject, () => w(index));
  72. } else {
  73. const requestOptions = differentialDownloader.createRequestOptions("get");
  74. requestOptions.headers.Range = `bytes=${task.start}-${task.end - 1}`;
  75. const request = differentialDownloader.httpExecutor.doRequest(requestOptions, response => {
  76. if (!checkIsRangesSupported(response, reject)) {
  77. return;
  78. }
  79. response.pipe(out, {
  80. end: false
  81. });
  82. response.once("end", () => w(index));
  83. });
  84. differentialDownloader.httpExecutor.addErrorAndTimeoutHandlers(request, reject);
  85. request.end();
  86. }
  87. };
  88. w(options.start);
  89. return;
  90. }
  91. const requestOptions = differentialDownloader.createRequestOptions("get");
  92. requestOptions.headers.Range = ranges.substring(0, ranges.length - 2);
  93. const request = differentialDownloader.httpExecutor.doRequest(requestOptions, response => {
  94. if (!checkIsRangesSupported(response, reject)) {
  95. return;
  96. }
  97. const contentType = (0, _builderUtilRuntime().safeGetHeader)(response, "content-type");
  98. const m = /^multipart\/.+?(?:; boundary=(?:(?:"(.+)")|(?:([^\s]+))))$/i.exec(contentType);
  99. if (m == null) {
  100. reject(new Error(`Content-Type "multipart/byteranges" is expected, but got "${contentType}"`));
  101. return;
  102. }
  103. const dicer = new (_DataSplitter().DataSplitter)(out, options, partIndexToTaskIndex, m[1] || m[2], partIndexToLength, resolve);
  104. dicer.on("error", reject);
  105. response.pipe(dicer);
  106. });
  107. differentialDownloader.httpExecutor.addErrorAndTimeoutHandlers(request, reject);
  108. request.end();
  109. }
  110. function checkIsRangesSupported(response, reject) {
  111. // Electron net handles redirects automatically, our NodeJS test server doesn't use redirects - so, we don't check 3xx codes.
  112. if (response.statusCode >= 400) {
  113. reject((0, _builderUtilRuntime().createHttpError)(response));
  114. return false;
  115. }
  116. if (response.statusCode !== 206) {
  117. const acceptRanges = (0, _builderUtilRuntime().safeGetHeader)(response, "accept-ranges");
  118. if (acceptRanges == null || acceptRanges === "none") {
  119. reject(new Error(`Server doesn't support Accept-Ranges (response code ${response.statusCode})`));
  120. return false;
  121. }
  122. }
  123. return true;
  124. }
  125. //# sourceMappingURL=multipleRangeDownloader.js.map