{"version":3,"file":"multipleRangeDownloader.js","sourceRoot":"","sources":["../../src/differentialDownloader/multipleRangeDownloader.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHttpError, safeGetHeader } from \"builder-util-runtime\"\nimport { IncomingMessage } from \"http\"\nimport { Writable } from \"stream\"\nimport { copyData, DataSplitter, PartListDataTask } from \"./DataSplitter\"\nimport { DifferentialDownloader } from \"./DifferentialDownloader\"\nimport { Operation, OperationKind } from \"./downloadPlanBuilder\"\n\nexport function executeTasksUsingMultipleRangeRequests(\n  differentialDownloader: DifferentialDownloader,\n  tasks: Array<Operation>,\n  out: Writable,\n  oldFileFd: number,\n  reject: (error: Error) => void\n): (taskOffset: number) => void {\n  const w = (taskOffset: number): void => {\n    if (taskOffset >= tasks.length) {\n      if (differentialDownloader.fileMetadataBuffer != null) {\n        out.write(differentialDownloader.fileMetadataBuffer)\n      }\n      out.end()\n      return\n    }\n\n    const nextOffset = taskOffset + 1000\n    doExecuteTasks(\n      differentialDownloader,\n      {\n        tasks,\n        start: taskOffset,\n        end: Math.min(tasks.length, nextOffset),\n        oldFileFd,\n      },\n      out,\n      () => w(nextOffset),\n      reject\n    )\n  }\n  return w\n}\n\nfunction doExecuteTasks(differentialDownloader: DifferentialDownloader, options: PartListDataTask, out: Writable, resolve: () => void, reject: (error: Error) => void): void {\n  let ranges = \"bytes=\"\n  let partCount = 0\n  let grandTotalBytes = 0\n  const partIndexToTaskIndex = new Map<number, number>()\n  const partIndexToLength: Array<number> = []\n  for (let i = options.start; i < options.end; i++) {\n    const task = options.tasks[i]\n    if (task.kind === OperationKind.DOWNLOAD) {\n      ranges += `${task.start}-${task.end - 1}, `\n      partIndexToTaskIndex.set(partCount, i)\n      partCount++\n      partIndexToLength.push(task.end - task.start)\n      grandTotalBytes += task.end - task.start\n    }\n  }\n\n  if (partCount <= 1) {\n    // the only remote range - copy\n    const w = (index: number): void => {\n      if (index >= options.end) {\n        resolve()\n        return\n      }\n\n      const task = options.tasks[index++]\n\n      if (task.kind === OperationKind.COPY) {\n        copyData(task, out, options.oldFileFd, reject, () => w(index))\n      } else {\n        const requestOptions = differentialDownloader.createRequestOptions()\n        requestOptions.headers!.Range = `bytes=${task.start}-${task.end - 1}`\n        const request = differentialDownloader.httpExecutor.createRequest(requestOptions, response => {\n          response.on(\"error\", reject)\n\n          if (!checkIsRangesSupported(response, reject)) {\n            return\n          }\n\n          response.pipe(out, {\n            end: false,\n          })\n          response.once(\"end\", () => w(index))\n        })\n        differentialDownloader.httpExecutor.addErrorAndTimeoutHandlers(request, reject)\n        request.end()\n      }\n    }\n\n    w(options.start)\n    return\n  }\n\n  const requestOptions = differentialDownloader.createRequestOptions()\n  requestOptions.headers!.Range = ranges.substring(0, ranges.length - 2)\n  const request = differentialDownloader.httpExecutor.createRequest(requestOptions, response => {\n    if (!checkIsRangesSupported(response, reject)) {\n      return\n    }\n\n    const contentType = safeGetHeader(response, \"content-type\")\n    const m = /^multipart\\/.+?\\s*;\\s*boundary=(?:\"([^\"]+)\"|([^\\s\";]+))\\s*$/i.exec(contentType)\n    if (m == null) {\n      reject(new Error(`Content-Type \"multipart/byteranges\" is expected, but got \"${contentType}\"`))\n      return\n    }\n\n    const dicer = new DataSplitter(out, options, partIndexToTaskIndex, m[1] || m[2], partIndexToLength, resolve, grandTotalBytes, differentialDownloader.options.onProgress)\n    dicer.on(\"error\", reject)\n    response.pipe(dicer)\n\n    response.on(\"end\", () => {\n      setTimeout(() => {\n        request.abort()\n        reject(new Error(\"Response ends without calling any handlers\"))\n      }, 10000)\n    })\n  })\n  differentialDownloader.httpExecutor.addErrorAndTimeoutHandlers(request, reject)\n  request.end()\n}\n\nexport function checkIsRangesSupported(response: IncomingMessage, reject: (error: Error) => void): boolean {\n  // Electron net handles redirects automatically, our NodeJS test server doesn't use redirects - so, we don't check 3xx codes.\n  if (response.statusCode! >= 400) {\n    reject(createHttpError(response))\n    return false\n  }\n\n  if (response.statusCode !== 206) {\n    const acceptRanges = safeGetHeader(response, \"accept-ranges\")\n    if (acceptRanges == null || acceptRanges === \"none\") {\n      reject(new Error(`Server doesn't support Accept-Ranges (response code ${response.statusCode})`))\n      return false\n    }\n  }\n  return true\n}\n"]}