@azure/communication-call-automation
Version:
Azure client library for Azure Communication Call Automation services
132 lines • 5.65 kB
JavaScript
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
import { createHttpHeaders, createPipelineRequest } from "@azure/core-rest-pipeline";
import { validateRecordingUrl } from "./utli/recordingUrlValidator.js";
/** Class containing ContentDownloading operations. */
export class ContentDownloaderImpl {
client;
/**
* Initialize a new instance of the class ContentDownloader class.
* @param client - Reference to the service client
*/
constructor(client) {
this.client = client;
this.addCustomSignUrlPolicy();
}
addCustomSignUrlPolicy() {
const signUrlPolicy = {
name: "CustomSignUrlPolicy",
async sendRequest(request, next) {
if (request.headers.has("OriginalUrl")) {
request.url = `${request.headers.get("OriginalUrl")}`;
const originalRequest = new URL(request.url);
request.headers.set("Host", originalRequest.host);
}
return next(request);
},
};
const pipelineOptions = {};
pipelineOptions.afterPhase = "Sign";
this.client.pipeline.addPolicy(signUrlPolicy, pipelineOptions);
}
/**
* Deletes a recording.
* @param deleteLocationUrl - The recording location url. Required.
*/
async deleteRecording(deleteLocationUrl, options) {
// Validate the recording URL before processing
validateRecordingUrl(deleteLocationUrl, "deleteLocationUrl");
const fileLocation = new URL(deleteLocationUrl);
const endpoint = new URL(this.client.endpoint);
const modifiedUrlForSigning = endpoint.origin + fileLocation.pathname;
const opt = {
url: modifiedUrlForSigning,
method: "DELETE",
headers: createHttpHeaders(),
body: "",
abortSignal: options?.abortSignal,
tracingOptions: options?.tracingOptions,
};
opt.headers?.set("OriginalUrl", deleteLocationUrl);
opt.headers?.set("x-ms-host", endpoint.host);
opt.headers?.set("accept", "application/json");
const req = createPipelineRequest(opt);
const results = await this.client.sendRequest(req);
if (results.status !== 200) {
if (results.bodyAsText) {
const jsonBody = JSON.parse(results.bodyAsText);
throw { status: jsonBody.status, message: jsonBody.message };
}
throw { status: results.status };
}
}
/**
* Returns a stream with a call recording.
* @param sourceLocationUrl - The source location url. Required.
* @param options - Additional request options contains downloadRecording options.
*/
async download(sourceLocationUrl, options) {
// Validate the recording URL before processing
validateRecordingUrl(sourceLocationUrl, "sourceLocationUrl");
const fileLocation = new URL(sourceLocationUrl);
const endpoint = new URL(this.client.endpoint);
const modifiedUrlForSigning = endpoint.origin + fileLocation.pathname;
const opt = {
url: modifiedUrlForSigning,
method: "GET",
headers: createHttpHeaders(),
body: "",
streamResponseStatusCodes: new Set([200, 206]),
abortSignal: options.abortSignal,
tracingOptions: options?.tracingOptions,
};
// Validate range parameters
if (options.length && !options.offset) {
throw new Error("Download offset value must not be empty if length is set.");
}
// Set standard headers
opt.headers?.set("OriginalUrl", sourceLocationUrl);
opt.headers?.set("x-ms-host", endpoint.host);
opt.headers?.set("accept", "application/json");
// Add Range header if partial download is requested
if (options.offset !== undefined) {
const rangeHeader = this.buildRangeHeader(options.offset, options.length);
opt.headers?.set("Range", rangeHeader);
}
const req = createPipelineRequest(opt);
const results = await this.client.sendRequest(req);
if (results.status !== 200 && results.status !== 206) {
if (results.bodyAsText) {
const jsonBody = JSON.parse(results.bodyAsText);
throw { status: jsonBody.status, message: jsonBody.message };
}
throw { status: results.status };
}
return results;
}
/**
* Builds HTTP Range header for partial content requests.
* @param offset - Starting byte position (0-based)
* @param length - Number of bytes to download (optional)
* @returns Formatted Range header value
*
* @example
* buildRangeHeader(1, 100) // "bytes=1-100" (first 100 bytes)
* buildRangeHeader(100, 50) // "bytes=100-149" (50 bytes starting at 100)
* buildRangeHeader(100) // "bytes=100-" (from byte 100 to end)
*/
buildRangeHeader(offset, length) {
// HTTP Range header uses inclusive end position
// Format: "bytes=start-end" where both start and end are inclusive
if (length !== undefined && length > 0) {
// Calculate inclusive end position from offset and length
const endPosition = offset + length - 1;
return `bytes=${offset}-${endPosition}`;
}
else {
// Open-ended range: from offset to end of file
return `bytes=${offset}-`;
}
}
}
//# sourceMappingURL=contentDownloader.js.map