@fluidframework/odsp-driver 0.55.2 → 0.56.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/checkUrl.d.ts.map +1 -1
- package/dist/checkUrl.js +0 -1
- package/dist/checkUrl.js.map +1 -1
- package/dist/contractsPublic.d.ts +7 -1
- package/dist/contractsPublic.d.ts.map +1 -1
- package/dist/contractsPublic.js +7 -1
- package/dist/contractsPublic.js.map +1 -1
- package/dist/createFile.d.ts +3 -3
- package/dist/createFile.d.ts.map +1 -1
- package/dist/createFile.js +7 -7
- package/dist/createFile.js.map +1 -1
- package/dist/epochTracker.d.ts +3 -3
- package/dist/epochTracker.d.ts.map +1 -1
- package/dist/epochTracker.js +20 -8
- package/dist/epochTracker.js.map +1 -1
- package/dist/fetchSnapshot.d.ts +3 -2
- package/dist/fetchSnapshot.d.ts.map +1 -1
- package/dist/fetchSnapshot.js +28 -16
- package/dist/fetchSnapshot.js.map +1 -1
- package/dist/getFileLink.js +4 -4
- package/dist/getFileLink.js.map +1 -1
- package/dist/getUrlAndHeadersWithAuth.d.ts +1 -1
- package/dist/getUrlAndHeadersWithAuth.d.ts.map +1 -1
- package/dist/getUrlAndHeadersWithAuth.js +20 -33
- package/dist/getUrlAndHeadersWithAuth.js.map +1 -1
- package/dist/odspDeltaStorageService.d.ts.map +1 -1
- package/dist/odspDeltaStorageService.js +1 -4
- package/dist/odspDeltaStorageService.js.map +1 -1
- package/dist/odspDocumentServiceFactoryCore.d.ts.map +1 -1
- package/dist/odspDocumentServiceFactoryCore.js +2 -2
- package/dist/odspDocumentServiceFactoryCore.js.map +1 -1
- package/dist/odspDocumentStorageManager.d.ts +1 -0
- package/dist/odspDocumentStorageManager.d.ts.map +1 -1
- package/dist/odspDocumentStorageManager.js +16 -9
- package/dist/odspDocumentStorageManager.js.map +1 -1
- package/dist/odspDriverUrlResolver.d.ts.map +1 -1
- package/dist/odspDriverUrlResolver.js +5 -2
- package/dist/odspDriverUrlResolver.js.map +1 -1
- package/dist/odspDriverUrlResolverForShareLink.d.ts.map +1 -1
- package/dist/odspDriverUrlResolverForShareLink.js +1 -2
- package/dist/odspDriverUrlResolverForShareLink.js.map +1 -1
- package/dist/odspSummaryUploadManager.d.ts +2 -1
- package/dist/odspSummaryUploadManager.d.ts.map +1 -1
- package/dist/odspSummaryUploadManager.js +3 -2
- package/dist/odspSummaryUploadManager.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/prefetchLatestSnapshot.d.ts +2 -1
- package/dist/prefetchLatestSnapshot.d.ts.map +1 -1
- package/dist/prefetchLatestSnapshot.js +3 -2
- package/dist/prefetchLatestSnapshot.js.map +1 -1
- package/dist/retryErrorsStorageAdapter.d.ts +1 -1
- package/dist/retryErrorsStorageAdapter.d.ts.map +1 -1
- package/dist/retryErrorsStorageAdapter.js.map +1 -1
- package/lib/checkUrl.d.ts.map +1 -1
- package/lib/checkUrl.js +0 -1
- package/lib/checkUrl.js.map +1 -1
- package/lib/contractsPublic.d.ts +7 -1
- package/lib/contractsPublic.d.ts.map +1 -1
- package/lib/contractsPublic.js +6 -0
- package/lib/contractsPublic.js.map +1 -1
- package/lib/createFile.d.ts +3 -3
- package/lib/createFile.d.ts.map +1 -1
- package/lib/createFile.js +7 -7
- package/lib/createFile.js.map +1 -1
- package/lib/epochTracker.d.ts +3 -3
- package/lib/epochTracker.d.ts.map +1 -1
- package/lib/epochTracker.js +21 -9
- package/lib/epochTracker.js.map +1 -1
- package/lib/fetchSnapshot.d.ts +3 -2
- package/lib/fetchSnapshot.d.ts.map +1 -1
- package/lib/fetchSnapshot.js +28 -16
- package/lib/fetchSnapshot.js.map +1 -1
- package/lib/getFileLink.js +4 -4
- package/lib/getFileLink.js.map +1 -1
- package/lib/getUrlAndHeadersWithAuth.d.ts +1 -1
- package/lib/getUrlAndHeadersWithAuth.d.ts.map +1 -1
- package/lib/getUrlAndHeadersWithAuth.js +20 -33
- package/lib/getUrlAndHeadersWithAuth.js.map +1 -1
- package/lib/odspDeltaStorageService.d.ts.map +1 -1
- package/lib/odspDeltaStorageService.js +1 -4
- package/lib/odspDeltaStorageService.js.map +1 -1
- package/lib/odspDocumentServiceFactoryCore.d.ts.map +1 -1
- package/lib/odspDocumentServiceFactoryCore.js +2 -2
- package/lib/odspDocumentServiceFactoryCore.js.map +1 -1
- package/lib/odspDocumentStorageManager.d.ts +1 -0
- package/lib/odspDocumentStorageManager.d.ts.map +1 -1
- package/lib/odspDocumentStorageManager.js +16 -9
- package/lib/odspDocumentStorageManager.js.map +1 -1
- package/lib/odspDriverUrlResolver.d.ts.map +1 -1
- package/lib/odspDriverUrlResolver.js +5 -2
- package/lib/odspDriverUrlResolver.js.map +1 -1
- package/lib/odspDriverUrlResolverForShareLink.d.ts.map +1 -1
- package/lib/odspDriverUrlResolverForShareLink.js +1 -2
- package/lib/odspDriverUrlResolverForShareLink.js.map +1 -1
- package/lib/odspSummaryUploadManager.d.ts +2 -1
- package/lib/odspSummaryUploadManager.d.ts.map +1 -1
- package/lib/odspSummaryUploadManager.js +3 -2
- package/lib/odspSummaryUploadManager.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/prefetchLatestSnapshot.d.ts +2 -1
- package/lib/prefetchLatestSnapshot.d.ts.map +1 -1
- package/lib/prefetchLatestSnapshot.js +3 -2
- package/lib/prefetchLatestSnapshot.js.map +1 -1
- package/lib/retryErrorsStorageAdapter.d.ts +1 -1
- package/lib/retryErrorsStorageAdapter.d.ts.map +1 -1
- package/lib/retryErrorsStorageAdapter.js.map +1 -1
- package/package.json +9 -9
- package/src/checkUrl.ts +0 -1
- package/src/contractsPublic.ts +11 -1
- package/src/createFile.ts +16 -4
- package/src/epochTracker.ts +21 -6
- package/src/fetchSnapshot.ts +33 -16
- package/src/getFileLink.ts +7 -2
- package/src/getUrlAndHeadersWithAuth.ts +24 -38
- package/src/odspDeltaStorageService.ts +1 -3
- package/src/odspDocumentServiceFactoryCore.ts +1 -0
- package/src/odspDocumentStorageManager.ts +39 -8
- package/src/odspDriverUrlResolver.ts +3 -0
- package/src/odspDriverUrlResolverForShareLink.ts +1 -2
- package/src/odspSummaryUploadManager.ts +6 -1
- package/src/packageVersion.ts +1 -1
- package/src/prefetchLatestSnapshot.ts +3 -0
- package/src/retryErrorsStorageAdapter.ts +1 -1
package/lib/fetchSnapshot.js
CHANGED
|
@@ -22,9 +22,10 @@ import { ReadBuffer } from "./ReadBufferUtils";
|
|
|
22
22
|
* @param storageFetchWrapper - Implementation of the get/post methods used to fetch the snapshot
|
|
23
23
|
* @param versionId - id of specific snapshot to be fetched
|
|
24
24
|
* @param fetchFullSnapshot - whether we want to fetch full snapshot(with blobs)
|
|
25
|
+
* @param forceAccessTokenViaAuthorizationHeader - whether to force passing given token via authorization header
|
|
25
26
|
* @returns A promise of the snapshot and the status code of the response
|
|
26
27
|
*/
|
|
27
|
-
export async function fetchSnapshot(snapshotUrl, token, versionId, fetchFullSnapshot, logger, snapshotDownloader) {
|
|
28
|
+
export async function fetchSnapshot(snapshotUrl, token, versionId, fetchFullSnapshot, forceAccessTokenViaAuthorizationHeader, logger, snapshotDownloader) {
|
|
28
29
|
const path = `/trees/${versionId}`;
|
|
29
30
|
let queryParams = {};
|
|
30
31
|
if (fetchFullSnapshot) {
|
|
@@ -36,14 +37,19 @@ export async function fetchSnapshot(snapshotUrl, token, versionId, fetchFullSnap
|
|
|
36
37
|
}
|
|
37
38
|
}
|
|
38
39
|
const queryString = getQueryString(queryParams);
|
|
39
|
-
const { url, headers } = getUrlAndHeadersWithAuth(`${snapshotUrl}${path}${queryString}`, token);
|
|
40
|
+
const { url, headers } = getUrlAndHeadersWithAuth(`${snapshotUrl}${path}${queryString}`, token, forceAccessTokenViaAuthorizationHeader);
|
|
40
41
|
const response = await PerformanceEvent.timedExecAsync(logger, {
|
|
41
42
|
eventName: "fetchSnapshot",
|
|
42
43
|
headers: Object.keys(headers).length !== 0 ? true : undefined,
|
|
43
44
|
}, async () => snapshotDownloader(url, { headers }));
|
|
44
45
|
return convertOdspSnapshotToSnapsohtTreeAndBlobs(response.content);
|
|
45
46
|
}
|
|
46
|
-
export async function fetchSnapshotWithRedeem(odspResolvedUrl, storageTokenFetcher, snapshotOptions, logger, snapshotDownloader, putInCache, removeEntries, enableRedeemFallback) {
|
|
47
|
+
export async function fetchSnapshotWithRedeem(odspResolvedUrl, storageTokenFetcher, snapshotOptions, forceAccessTokenViaAuthorizationHeader, logger, snapshotDownloader, putInCache, removeEntries, enableRedeemFallback) {
|
|
48
|
+
// back-compat: This block to be removed with #8784 when we only consume/consider odsp resolvers that are >= 0.51
|
|
49
|
+
const sharingLinkToRedeem = odspResolvedUrl.sharingLinkToRedeem;
|
|
50
|
+
if (sharingLinkToRedeem) {
|
|
51
|
+
odspResolvedUrl.shareLinkInfo = Object.assign(Object.assign({}, odspResolvedUrl.shareLinkInfo), { sharingLinkToRedeem });
|
|
52
|
+
}
|
|
47
53
|
return fetchLatestSnapshotCore(odspResolvedUrl, storageTokenFetcher, snapshotOptions, logger, snapshotDownloader, putInCache, enableRedeemFallback).catch(async (error) => {
|
|
48
54
|
if (enableRedeemFallback && isRedeemSharingLinkError(odspResolvedUrl, error)) {
|
|
49
55
|
// Execute the redeem fallback
|
|
@@ -51,11 +57,8 @@ export async function fetchSnapshotWithRedeem(odspResolvedUrl, storageTokenFetch
|
|
|
51
57
|
eventName: "RedeemFallback",
|
|
52
58
|
errorType: error.errorType,
|
|
53
59
|
}, error);
|
|
54
|
-
await redeemSharingLink(odspResolvedUrl, storageTokenFetcher, logger);
|
|
55
|
-
const odspResolvedUrlWithoutShareLink = Object.assign(Object.assign({}, odspResolvedUrl), { sharingLinkToRedeem: undefined });
|
|
56
|
-
if (odspResolvedUrlWithoutShareLink.shareLinkInfo) {
|
|
57
|
-
odspResolvedUrlWithoutShareLink.shareLinkInfo = Object.assign(Object.assign({}, odspResolvedUrlWithoutShareLink.shareLinkInfo), { sharingLinkToRedeem: undefined });
|
|
58
|
-
}
|
|
60
|
+
await redeemSharingLink(odspResolvedUrl, storageTokenFetcher, logger, forceAccessTokenViaAuthorizationHeader);
|
|
61
|
+
const odspResolvedUrlWithoutShareLink = Object.assign(Object.assign({}, odspResolvedUrl), { shareLinkInfo: Object.assign(Object.assign({}, odspResolvedUrl.shareLinkInfo), { sharingLinkToRedeem: undefined }) });
|
|
59
62
|
return fetchLatestSnapshotCore(odspResolvedUrlWithoutShareLink, storageTokenFetcher, snapshotOptions, logger, snapshotDownloader, putInCache);
|
|
60
63
|
}
|
|
61
64
|
else {
|
|
@@ -72,21 +75,23 @@ export async function fetchSnapshotWithRedeem(odspResolvedUrl, storageTokenFetch
|
|
|
72
75
|
throw error;
|
|
73
76
|
});
|
|
74
77
|
}
|
|
75
|
-
async function redeemSharingLink(odspResolvedUrl, storageTokenFetcher, logger) {
|
|
78
|
+
async function redeemSharingLink(odspResolvedUrl, storageTokenFetcher, logger, forceAccessTokenViaAuthorizationHeader) {
|
|
76
79
|
return PerformanceEvent.timedExecAsync(logger, {
|
|
77
80
|
eventName: "RedeemShareLink",
|
|
78
81
|
}, async () => getWithRetryForTokenRefresh(async (tokenFetchOptions) => {
|
|
79
|
-
|
|
82
|
+
var _a, _b;
|
|
83
|
+
assert(!!((_a = odspResolvedUrl.shareLinkInfo) === null || _a === void 0 ? void 0 : _a.sharingLinkToRedeem), 0x1ed /* "Share link should be present" */);
|
|
80
84
|
const storageToken = await storageTokenFetcher(tokenFetchOptions, "RedeemShareLink");
|
|
81
|
-
const encodedShareUrl = getEncodedShareUrl(odspResolvedUrl.sharingLinkToRedeem);
|
|
85
|
+
const encodedShareUrl = getEncodedShareUrl((_b = odspResolvedUrl.shareLinkInfo) === null || _b === void 0 ? void 0 : _b.sharingLinkToRedeem);
|
|
82
86
|
const redeemUrl = `${odspResolvedUrl.siteUrl}/_api/v2.0/shares/${encodedShareUrl}`;
|
|
83
|
-
const { url, headers } = getUrlAndHeadersWithAuth(redeemUrl, storageToken);
|
|
87
|
+
const { url, headers } = getUrlAndHeadersWithAuth(redeemUrl, storageToken, forceAccessTokenViaAuthorizationHeader);
|
|
84
88
|
headers.prefer = "redeemSharingLink";
|
|
85
89
|
return fetchAndParseAsJSONHelper(url, { headers });
|
|
86
90
|
}));
|
|
87
91
|
}
|
|
88
92
|
async function fetchLatestSnapshotCore(odspResolvedUrl, storageTokenFetcher, snapshotOptions, logger, snapshotDownloader, putInCache, enableRedeemFallback) {
|
|
89
93
|
return getWithRetryForTokenRefresh(async (tokenFetchOptions) => {
|
|
94
|
+
var _a;
|
|
90
95
|
const storageToken = await storageTokenFetcher(tokenFetchOptions, "TreesLatest", true);
|
|
91
96
|
assert(storageToken !== null, 0x1e5 /* "Storage token should not be null" */);
|
|
92
97
|
let controller;
|
|
@@ -97,7 +102,7 @@ async function fetchLatestSnapshotCore(odspResolvedUrl, storageTokenFetcher, sna
|
|
|
97
102
|
const perfEvent = {
|
|
98
103
|
eventName: "TreesLatest",
|
|
99
104
|
attempts: tokenFetchOptions.refresh ? 2 : 1,
|
|
100
|
-
shareLinkPresent: odspResolvedUrl.sharingLinkToRedeem !== undefined,
|
|
105
|
+
shareLinkPresent: ((_a = odspResolvedUrl.shareLinkInfo) === null || _a === void 0 ? void 0 : _a.sharingLinkToRedeem) !== undefined,
|
|
101
106
|
redeemFallbackEnabled: enableRedeemFallback,
|
|
102
107
|
};
|
|
103
108
|
if (snapshotOptions !== undefined) {
|
|
@@ -256,6 +261,7 @@ async function fetchSnapshotContentsCoreV2(odspResolvedUrl, storageToken, snapsh
|
|
|
256
261
|
};
|
|
257
262
|
}
|
|
258
263
|
function getFormBodyAndHeaders(odspResolvedUrl, storageToken, snapshotOptions) {
|
|
264
|
+
var _a, _b;
|
|
259
265
|
const formBoundary = uuid();
|
|
260
266
|
const formParams = [];
|
|
261
267
|
formParams.push(`--${formBoundary}`);
|
|
@@ -268,8 +274,8 @@ function getFormBodyAndHeaders(odspResolvedUrl, storageToken, snapshotOptions) {
|
|
|
268
274
|
}
|
|
269
275
|
});
|
|
270
276
|
}
|
|
271
|
-
if (odspResolvedUrl.sharingLinkToRedeem) {
|
|
272
|
-
formParams.push(`sl: ${odspResolvedUrl.sharingLinkToRedeem}`);
|
|
277
|
+
if ((_a = odspResolvedUrl.shareLinkInfo) === null || _a === void 0 ? void 0 : _a.sharingLinkToRedeem) {
|
|
278
|
+
formParams.push(`sl: ${(_b = odspResolvedUrl.shareLinkInfo) === null || _b === void 0 ? void 0 : _b.sharingLinkToRedeem}`);
|
|
273
279
|
}
|
|
274
280
|
formParams.push(`_post: 1`);
|
|
275
281
|
formParams.push(`\r\n--${formBoundary}--`);
|
|
@@ -299,6 +305,11 @@ function countTreesInSnapshotTree(snapshotTree) {
|
|
|
299
305
|
return numTrees;
|
|
300
306
|
}
|
|
301
307
|
export async function downloadSnapshot(odspResolvedUrl, storageToken, logger, snapshotOptions, fetchBinarySnapshotFormat, controller, epochTracker) {
|
|
308
|
+
// back-compat: This block to be removed with #8784 when we only consume/consider odsp resolvers that are >= 0.51
|
|
309
|
+
const sharingLinkToRedeem = odspResolvedUrl.sharingLinkToRedeem;
|
|
310
|
+
if (sharingLinkToRedeem) {
|
|
311
|
+
odspResolvedUrl.shareLinkInfo = Object.assign(Object.assign({}, odspResolvedUrl.shareLinkInfo), { sharingLinkToRedeem });
|
|
312
|
+
}
|
|
302
313
|
if (fetchBinarySnapshotFormat) {
|
|
303
314
|
// Logging an event here as it is not supposed to be used in production yet and only in experimental mode.
|
|
304
315
|
logger.sendTelemetryEvent({ eventName: "BinarySnapshotFetched" });
|
|
@@ -309,7 +320,8 @@ export async function downloadSnapshot(odspResolvedUrl, storageToken, logger, sn
|
|
|
309
320
|
}
|
|
310
321
|
}
|
|
311
322
|
function isRedeemSharingLinkError(odspResolvedUrl, error) {
|
|
312
|
-
|
|
323
|
+
var _a;
|
|
324
|
+
if (((_a = odspResolvedUrl.shareLinkInfo) === null || _a === void 0 ? void 0 : _a.sharingLinkToRedeem) !== undefined
|
|
313
325
|
&& (typeof error === "object" && error !== null)
|
|
314
326
|
&& (error.errorType === DriverErrorType.authorizationError
|
|
315
327
|
|| error.errorType === DriverErrorType.fileNotFoundOrAccessDeniedError)) {
|
package/lib/fetchSnapshot.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fetchSnapshot.js","sourceRoot":"","sources":["../src/fetchSnapshot.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { default as AbortController } from \"abort-controller\";\nimport { v4 as uuid } from \"uuid\";\nimport { ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { assert, fromUtf8ToBase64, performance } from \"@fluidframework/common-utils\";\nimport { DriverErrorType } from \"@fluidframework/driver-definitions\";\nimport { PerformanceEvent } from \"@fluidframework/telemetry-utils\";\nimport {\n IOdspResolvedUrl,\n ISnapshotOptions,\n OdspErrorType,\n InstrumentedStorageTokenFetcher,\n} from \"@fluidframework/odsp-driver-definitions\";\nimport { ISnapshotTree } from \"@fluidframework/protocol-definitions\";\nimport { IOdspSnapshot, ISnapshotCachedEntry, IVersionedValueWithEpoch, persistedCacheValueVersion } from \"./contracts\";\nimport { getQueryString } from \"./getQueryString\";\nimport { getUrlAndHeadersWithAuth } from \"./getUrlAndHeadersWithAuth\";\nimport {\n fetchAndParseAsJSONHelper,\n fetchArray,\n getWithRetryForTokenRefresh,\n getWithRetryForTokenRefreshRepeat,\n IOdspResponse,\n ISnapshotContents,\n} from \"./odspUtils\";\nimport { convertOdspSnapshotToSnapsohtTreeAndBlobs } from \"./odspSnapshotParser\";\nimport { parseCompactSnapshotResponse } from \"./compactSnapshotParser\";\nimport { ReadBuffer } from \"./ReadBufferUtils\";\nimport { EpochTracker } from \"./epochTracker\";\n\n/**\n * Fetches a snapshot from the server with a given version id.\n * @param snapshotUrl - snapshot url from where the odsp snapshot will be fetched\n * @param token - token used for authorization in the request\n * @param storageFetchWrapper - Implementation of the get/post methods used to fetch the snapshot\n * @param versionId - id of specific snapshot to be fetched\n * @param fetchFullSnapshot - whether we want to fetch full snapshot(with blobs)\n * @returns A promise of the snapshot and the status code of the response\n */\nexport async function fetchSnapshot(\n snapshotUrl: string,\n token: string | null,\n versionId: string,\n fetchFullSnapshot: boolean,\n logger: ITelemetryLogger,\n snapshotDownloader: (url: string, fetchOptions: {[index: string]: any}) => Promise<IOdspResponse<unknown>>,\n): Promise<ISnapshotContents> {\n const path = `/trees/${versionId}`;\n let queryParams: ISnapshotOptions = {};\n\n if (fetchFullSnapshot) {\n if (versionId !== \"latest\") {\n queryParams = { channels: 1, blobs: 2 };\n } else {\n queryParams = { deltas: 1, channels: 1, blobs: 2 };\n }\n }\n\n const queryString = getQueryString(queryParams);\n const { url, headers } = getUrlAndHeadersWithAuth(`${snapshotUrl}${path}${queryString}`, token);\n const response = await PerformanceEvent.timedExecAsync(\n logger,\n {\n eventName: \"fetchSnapshot\",\n headers: Object.keys(headers).length !== 0 ? true : undefined,\n },\n async () => snapshotDownloader(url, { headers }),\n ) as IOdspResponse<IOdspSnapshot>;\n return convertOdspSnapshotToSnapsohtTreeAndBlobs(response.content);\n}\n\nexport async function fetchSnapshotWithRedeem(\n odspResolvedUrl: IOdspResolvedUrl,\n storageTokenFetcher: InstrumentedStorageTokenFetcher,\n snapshotOptions: ISnapshotOptions | undefined,\n logger: ITelemetryLogger,\n snapshotDownloader: (\n finalOdspResolvedUrl: IOdspResolvedUrl,\n storageToken: string,\n snapshotOptions: ISnapshotOptions | undefined,\n controller?: AbortController,\n ) => Promise<ISnapshotRequestAndResponseOptions>,\n putInCache: (valueWithEpoch: IVersionedValueWithEpoch) => Promise<void>,\n removeEntries: () => Promise<void>,\n enableRedeemFallback?: boolean,\n): Promise<ISnapshotContents> {\n return fetchLatestSnapshotCore(\n odspResolvedUrl,\n storageTokenFetcher,\n snapshotOptions,\n logger,\n snapshotDownloader,\n putInCache,\n enableRedeemFallback,\n ).catch(async (error) => {\n if (enableRedeemFallback && isRedeemSharingLinkError(odspResolvedUrl, error)) {\n // Execute the redeem fallback\n logger.sendErrorEvent({\n eventName: \"RedeemFallback\",\n errorType: error.errorType,\n }, error);\n await redeemSharingLink(odspResolvedUrl, storageTokenFetcher, logger);\n const odspResolvedUrlWithoutShareLink: IOdspResolvedUrl =\n { ...odspResolvedUrl, sharingLinkToRedeem: undefined };\n\n if(odspResolvedUrlWithoutShareLink.shareLinkInfo) {\n odspResolvedUrlWithoutShareLink.shareLinkInfo = {\n ...odspResolvedUrlWithoutShareLink.shareLinkInfo,\n sharingLinkToRedeem: undefined,\n };\n }\n\n return fetchLatestSnapshotCore(\n odspResolvedUrlWithoutShareLink,\n storageTokenFetcher,\n snapshotOptions,\n logger,\n snapshotDownloader,\n putInCache,\n );\n } else {\n throw error;\n }\n }).catch(async (error) => {\n // Clear the cache on 401/403/404 on snapshot fetch from network because this means either the user doesn't\n // have permissions for the file or it was deleted. So, if we do not clear cache, we will continue fetching\n // snapshot from cache in the future.\n if (typeof error === \"object\" && error !== null && error.errorType === DriverErrorType.authorizationError\n || error.errorType === DriverErrorType.fileNotFoundOrAccessDeniedError) {\n await removeEntries();\n }\n throw error;\n });\n}\n\nasync function redeemSharingLink(\n odspResolvedUrl: IOdspResolvedUrl,\n storageTokenFetcher: InstrumentedStorageTokenFetcher,\n logger: ITelemetryLogger,\n) {\n return PerformanceEvent.timedExecAsync(\n logger,\n {\n eventName: \"RedeemShareLink\",\n },\n async () => getWithRetryForTokenRefresh(async (tokenFetchOptions) => {\n assert(!!odspResolvedUrl.sharingLinkToRedeem,\n 0x1ed /* \"Share link should be present\" */);\n const storageToken = await storageTokenFetcher(tokenFetchOptions, \"RedeemShareLink\");\n const encodedShareUrl = getEncodedShareUrl(odspResolvedUrl.sharingLinkToRedeem);\n const redeemUrl = `${odspResolvedUrl.siteUrl}/_api/v2.0/shares/${encodedShareUrl}`;\n const { url, headers } = getUrlAndHeadersWithAuth(redeemUrl, storageToken);\n headers.prefer = \"redeemSharingLink\";\n return fetchAndParseAsJSONHelper(url, { headers });\n }),\n );\n}\n\nasync function fetchLatestSnapshotCore(\n odspResolvedUrl: IOdspResolvedUrl,\n storageTokenFetcher: InstrumentedStorageTokenFetcher,\n snapshotOptions: ISnapshotOptions | undefined,\n logger: ITelemetryLogger,\n snapshotDownloader: (\n finalOdspResolvedUrl: IOdspResolvedUrl,\n storageToken: string,\n snapshotOptions: ISnapshotOptions | undefined,\n controller?: AbortController,\n ) => Promise<ISnapshotRequestAndResponseOptions>,\n putInCache: (valueWithEpoch: IVersionedValueWithEpoch) => Promise<void>,\n enableRedeemFallback?: boolean,\n): Promise<ISnapshotContents> {\n return getWithRetryForTokenRefresh(async (tokenFetchOptions) => {\n const storageToken = await storageTokenFetcher(tokenFetchOptions, \"TreesLatest\", true);\n assert(storageToken !== null, 0x1e5 /* \"Storage token should not be null\" */);\n\n let controller: AbortController | undefined;\n if (snapshotOptions?.timeout !== undefined) {\n controller = new AbortController();\n setTimeout(\n () => controller!.abort(),\n snapshotOptions.timeout,\n );\n }\n const perfEvent = {\n eventName: \"TreesLatest\",\n attempts: tokenFetchOptions.refresh ? 2 : 1,\n shareLinkPresent: odspResolvedUrl.sharingLinkToRedeem !== undefined,\n redeemFallbackEnabled: enableRedeemFallback,\n };\n if (snapshotOptions !== undefined) {\n Object.entries(snapshotOptions).forEach(([key, value]) => {\n if (value !== undefined) {\n perfEvent[`snapshotOption_${key}`] = value;\n }\n });\n }\n // This event measures only successful cases of getLatest call (no tokens, no retries).\n return PerformanceEvent.timedExecAsync(\n logger,\n perfEvent,\n async (event) => {\n const startTime = performance.now();\n const response = await snapshotDownloader(\n odspResolvedUrl,\n storageToken,\n snapshotOptions,\n controller,\n );\n const endTime = performance.now();\n const overallTime = endTime - startTime;\n const snapshot = response.odspSnapshotResponse.content;\n let dnstime: number | undefined; // domainLookupEnd - domainLookupStart\n let redirectTime: number | undefined; // redirectEnd -redirectStart\n let tcpHandshakeTime: number | undefined; // connectEnd - connectStart\n let secureConntime: number | undefined; // connectEnd - secureConnectionStart\n let responseTime: number | undefined; // responsEnd - responseStart\n let fetchStToRespEndTime: number | undefined; // responseEnd - fetchStart\n let reqStToRespEndTime: number | undefined; // responseEnd - requestStart\n let networkTime: number | undefined; // responseEnd - startTime\n const spReqDuration = response.odspSnapshotResponse.headers.get(\"sprequestduration\");\n\n // getEntriesByType is only available in browser performance object\n const resources1 = performance.getEntriesByType?.(\"resource\") ?? [];\n // Usually the latest fetch call is to the end of resources, so we start from the end.\n for (let i = resources1.length - 1; i > 0; i--) {\n const indResTime = resources1[i] as PerformanceResourceTiming;\n const resource_name = indResTime.name;\n const resource_initiatortype = indResTime.initiatorType;\n if ((resource_initiatortype.localeCompare(\"fetch\") === 0)\n && (resource_name.localeCompare(response.requestUrl) === 0)) {\n redirectTime = indResTime.redirectEnd - indResTime.redirectStart;\n dnstime = indResTime.domainLookupEnd - indResTime.domainLookupStart;\n tcpHandshakeTime = indResTime.connectEnd - indResTime.connectStart;\n secureConntime = (indResTime.secureConnectionStart > 0) ?\n (indResTime.connectEnd - indResTime.secureConnectionStart) : 0;\n responseTime = indResTime.responseEnd - indResTime.responseStart;\n fetchStToRespEndTime = (indResTime.fetchStart > 0) ?\n (indResTime.responseEnd - indResTime.fetchStart) : 0;\n reqStToRespEndTime = (indResTime.requestStart > 0) ?\n (indResTime.responseEnd - indResTime.requestStart) : 0;\n networkTime = (indResTime.startTime > 0) ? (indResTime.responseEnd - indResTime.startTime) : 0;\n if (spReqDuration) {\n networkTime = networkTime - parseInt(spReqDuration, 10);\n }\n break;\n }\n }\n\n const { numTrees, numBlobs, encodedBlobsSize } =\n validateAndEvalBlobsAndTrees(response.odspSnapshotResponse.content);\n const clientTime = networkTime ? overallTime - networkTime : undefined;\n\n // There are some scenarios in ODSP where we cannot cache, trees/latest will explicitly tell us when we\n // cannot cache using an HTTP response header.\n const canCache =\n response.odspSnapshotResponse.headers.get(\"disablebrowsercachingofusercontent\") !== \"true\";\n const sequenceNumber: number = snapshot.sequenceNumber ?? 0;\n const seqNumberFromOps = snapshot.ops && snapshot.ops.length > 0 ?\n snapshot.ops[0].sequenceNumber - 1 :\n undefined;\n\n if (!Number.isInteger(sequenceNumber)\n || seqNumberFromOps !== undefined && seqNumberFromOps !== sequenceNumber) {\n logger.sendErrorEvent({ eventName: \"fetchSnapshotError\", sequenceNumber, seqNumberFromOps });\n snapshot.sequenceNumber = undefined;\n } else if (canCache) {\n const fluidEpoch = response.odspSnapshotResponse.headers.get(\"x-fluid-epoch\");\n assert(fluidEpoch !== undefined, 0x1e6 /* \"Epoch should be present in response\" */);\n const value: ISnapshotCachedEntry = {\n ...snapshot,\n cacheEntryTime: Date.now(),\n };\n const valueWithEpoch: IVersionedValueWithEpoch = {\n value,\n fluidEpoch,\n version: persistedCacheValueVersion,\n };\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n putInCache(valueWithEpoch);\n }\n event.end({\n trees: numTrees,\n blobs: snapshot.blobs?.size ?? 0,\n leafNodes: numBlobs,\n encodedBlobsSize,\n sequenceNumber,\n ops: snapshot.ops?.length ?? 0,\n headers: Object.keys(response.requestHeaders).length !== 0 ? true : undefined,\n redirecttime: redirectTime,\n dnsLookuptime: dnstime,\n responsenetworkTime: responseTime,\n tcphandshakeTime: tcpHandshakeTime,\n secureconnectiontime: secureConntime,\n fetchstarttorespendtime: fetchStToRespEndTime,\n reqstarttorespendtime: reqStToRespEndTime,\n overalltime: overallTime,\n networktime: networkTime,\n clienttime: clientTime,\n // Sharing link telemetry regarding sharing link redeem status and performance. Ex: FRL; dur=100,\n // Azure Fluid Relay service; desc=S, FRP; desc=False. Here, FRL is the duration taken for redeem,\n // Azure Fluid Relay service is the redeem status (S means success), and FRP is a flag to indicate\n // if the permission has changed.\n sltelemetry: response.odspSnapshotResponse.headers.get(\"x-fluid-sltelemetry\"),\n ...response.odspSnapshotResponse.commonSpoHeaders,\n });\n return snapshot;\n },\n ).catch((error) => {\n // We hit these errors in stress tests, under load\n // It's useful to try one more time in such case.\n // We might want to add DriverErrorType.offlineError in the future if we see evidence it happens\n // (not in \"real\" offline) and it actually helps.\n if (typeof error === \"object\" && error !== null && (error.errorType === DriverErrorType.fetchFailure ||\n error.errorType === OdspErrorType.fetchTimeout)) {\n error[getWithRetryForTokenRefreshRepeat] = true;\n }\n throw error;\n });\n });\n}\n\ninterface ISnapshotRequestAndResponseOptions {\n odspSnapshotResponse: IOdspResponse<ISnapshotContents>,\n requestUrl: string,\n requestHeaders: {[index: string]: any},\n}\n\n/**\n * This function fetches the older snapshot format which is the json format(IOdspSnapshot).\n * @param odspResolvedUrl - resolved odsp url.\n * @param storageToken - token to do the auth for network request.\n * @param snapshotOptions - Options used to specify how and what to fetch in the snapshot.\n * @param controller - abort controller if caller needs to abort the network call.\n * @param epochTracker - epoch tracker used to add/validate epoch in the network call.\n * @returns fetched snapshot.\n */\nasync function fetchSnapshotContentsCoreV1(\n odspResolvedUrl: IOdspResolvedUrl,\n storageToken: string,\n snapshotOptions: ISnapshotOptions | undefined,\n controller?: AbortController,\n epochTracker?: EpochTracker,\n): Promise<ISnapshotRequestAndResponseOptions> {\n const snapshotUrl = odspResolvedUrl.endpoints.snapshotStorageUrl;\n const url = `${snapshotUrl}/trees/latest?ump=1`;\n const { body, headers } = getFormBodyAndHeaders(odspResolvedUrl, storageToken, snapshotOptions);\n const fetchOptions = {\n body,\n headers,\n signal: controller?.signal,\n method: \"POST\",\n };\n const response = await (epochTracker?.fetchAndParseAsJSON<IOdspSnapshot>(url, fetchOptions, \"treesLatest\", true) ??\n fetchAndParseAsJSONHelper<IOdspSnapshot>(url, fetchOptions));\n const snapshotContents: ISnapshotContents = convertOdspSnapshotToSnapsohtTreeAndBlobs(response.content);\n const finalSnapshotContents: IOdspResponse<ISnapshotContents> = { ...response, content: snapshotContents };\n return {\n odspSnapshotResponse: finalSnapshotContents,\n requestHeaders: headers,\n requestUrl: url,\n };\n}\n\n/**\n * This function fetches the binary compact snapshot format. This is an experimental feature\n * and is behind a feature flag.\n * @param odspResolvedUrl - resolved odsp url.\n * @param storageToken - token to do the auth for network request.\n * @param snapshotOptions - Options used to specify how and what to fetch in the snapshot.\n * @param controller - abort controller if caller needs to abort the network call.\n * @param epochTracker - epoch tracker used to add/validate epoch in the network call.\n * @returns fetched snapshot.\n */\nasync function fetchSnapshotContentsCoreV2(\n odspResolvedUrl: IOdspResolvedUrl,\n storageToken: string,\n snapshotOptions: ISnapshotOptions | undefined,\n controller?: AbortController,\n epochTracker?: EpochTracker,\n): Promise<ISnapshotRequestAndResponseOptions> {\n const fullUrl = `${odspResolvedUrl.siteUrl}/_api/v2.1/drives/${odspResolvedUrl.driveId}/items/${\n odspResolvedUrl.itemId}/opStream/attachments/latest/content?ump=1`;\n\n const { body, headers } = getFormBodyAndHeaders(odspResolvedUrl, storageToken, snapshotOptions);\n const fetchOptions = {\n body,\n headers,\n signal: controller?.signal,\n method: \"POST\",\n };\n\n const response = await (epochTracker?.fetchArray(fullUrl, fetchOptions, \"treesLatest\", true) ??\n fetchArray(fullUrl, fetchOptions));\n const snapshotContents: ISnapshotContents = parseCompactSnapshotResponse(\n new ReadBuffer(new Uint8Array(response.content)));\n const finalSnapshotContents: IOdspResponse<ISnapshotContents> = { ...response, content: snapshotContents };\n return {\n odspSnapshotResponse: finalSnapshotContents,\n requestHeaders: headers,\n requestUrl: fullUrl,\n };\n}\n\nfunction getFormBodyAndHeaders(\n odspResolvedUrl: IOdspResolvedUrl,\n storageToken: string,\n snapshotOptions: ISnapshotOptions | undefined,\n) {\n const formBoundary = uuid();\n const formParams: string[] = [];\n formParams.push(`--${formBoundary}`);\n formParams.push(`Authorization: Bearer ${storageToken}`);\n formParams.push(`X-HTTP-Method-Override: GET`);\n if (snapshotOptions !== undefined) {\n Object.entries(snapshotOptions).forEach(([key, value]) => {\n if (value !== undefined) {\n formParams.push(`${key}: ${value}`);\n }\n });\n }\n if (odspResolvedUrl.sharingLinkToRedeem) {\n formParams.push(`sl: ${odspResolvedUrl.sharingLinkToRedeem}`);\n }\n formParams.push(`_post: 1`);\n formParams.push(`\\r\\n--${formBoundary}--`);\n const postBody = formParams.join(\"\\r\\n\");\n const headers: {[index: string]: any} = {\n \"Content-Type\": `multipart/form-data;boundary=${formBoundary}`,\n };\n return { body: postBody, headers };\n}\n\nfunction validateAndEvalBlobsAndTrees(snapshot: ISnapshotContents) {\n assert(snapshot.snapshotTree !== undefined,\n 0x200 /* \"Returned odsp snapshot is malformed. No trees!\" */);\n assert(snapshot.blobs !== undefined,\n 0x201 /* \"Returned odsp snapshot is malformed. No blobs!\" */);\n const numTrees = countTreesInSnapshotTree(snapshot.snapshotTree);\n const numBlobs = snapshot.blobs.size;\n let encodedBlobsSize = 0;\n for (const [_, blobContent] of snapshot.blobs) {\n encodedBlobsSize += blobContent.byteLength;\n }\n return { numTrees, numBlobs, encodedBlobsSize };\n}\n\nfunction countTreesInSnapshotTree(snapshotTree: ISnapshotTree): number {\n let numTrees = 0;\n for (const [_, tree] of Object.entries(snapshotTree.trees)) {\n numTrees += 1;\n numTrees += countTreesInSnapshotTree(tree);\n }\n return numTrees;\n}\n\nexport async function downloadSnapshot(\n odspResolvedUrl: IOdspResolvedUrl,\n storageToken: string,\n logger: ITelemetryLogger,\n snapshotOptions: ISnapshotOptions | undefined,\n fetchBinarySnapshotFormat?: boolean,\n controller?: AbortController,\n epochTracker?: EpochTracker,\n): Promise<ISnapshotRequestAndResponseOptions> {\n if (fetchBinarySnapshotFormat) {\n // Logging an event here as it is not supposed to be used in production yet and only in experimental mode.\n logger.sendTelemetryEvent({ eventName: \"BinarySnapshotFetched\" });\n return fetchSnapshotContentsCoreV2(odspResolvedUrl, storageToken, snapshotOptions, controller, epochTracker);\n } else {\n return fetchSnapshotContentsCoreV1(odspResolvedUrl, storageToken, snapshotOptions, controller, epochTracker);\n }\n}\n\nfunction isRedeemSharingLinkError(odspResolvedUrl: IOdspResolvedUrl, error: any) {\n if (odspResolvedUrl.sharingLinkToRedeem !== undefined\n && (typeof error === \"object\" && error !== null)\n && (error.errorType === DriverErrorType.authorizationError\n || error.errorType === DriverErrorType.fileNotFoundOrAccessDeniedError)) {\n return true;\n }\n return false;\n}\n\nfunction getEncodedShareUrl(url: string): string {\n /**\n * Encode the url to accepted format by Sharepoint\n * https://docs.microsoft.com/en-us/onedrive/developer/rest-api/api/shares_get\n */\n let encodedUrl = fromUtf8ToBase64(encodeURI(url));\n encodedUrl = encodedUrl\n .replace(/=+$/g, \"\")\n .replace(/\\//g, \"_\")\n .replace(/\\+/g, \"-\");\n encodedUrl = \"u!\".concat(encodedUrl);\n return encodedUrl;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"fetchSnapshot.js","sourceRoot":"","sources":["../src/fetchSnapshot.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { default as AbortController } from \"abort-controller\";\nimport { v4 as uuid } from \"uuid\";\nimport { ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { assert, fromUtf8ToBase64, performance } from \"@fluidframework/common-utils\";\nimport { DriverErrorType } from \"@fluidframework/driver-definitions\";\nimport { PerformanceEvent } from \"@fluidframework/telemetry-utils\";\nimport {\n IOdspResolvedUrl,\n ISnapshotOptions,\n OdspErrorType,\n InstrumentedStorageTokenFetcher,\n} from \"@fluidframework/odsp-driver-definitions\";\nimport { ISnapshotTree } from \"@fluidframework/protocol-definitions\";\nimport { IOdspSnapshot, ISnapshotCachedEntry, IVersionedValueWithEpoch, persistedCacheValueVersion } from \"./contracts\";\nimport { getQueryString } from \"./getQueryString\";\nimport { getUrlAndHeadersWithAuth } from \"./getUrlAndHeadersWithAuth\";\nimport {\n fetchAndParseAsJSONHelper,\n fetchArray,\n getWithRetryForTokenRefresh,\n getWithRetryForTokenRefreshRepeat,\n IOdspResponse,\n ISnapshotContents,\n} from \"./odspUtils\";\nimport { convertOdspSnapshotToSnapsohtTreeAndBlobs } from \"./odspSnapshotParser\";\nimport { parseCompactSnapshotResponse } from \"./compactSnapshotParser\";\nimport { ReadBuffer } from \"./ReadBufferUtils\";\nimport { EpochTracker } from \"./epochTracker\";\n\n/**\n * Fetches a snapshot from the server with a given version id.\n * @param snapshotUrl - snapshot url from where the odsp snapshot will be fetched\n * @param token - token used for authorization in the request\n * @param storageFetchWrapper - Implementation of the get/post methods used to fetch the snapshot\n * @param versionId - id of specific snapshot to be fetched\n * @param fetchFullSnapshot - whether we want to fetch full snapshot(with blobs)\n * @param forceAccessTokenViaAuthorizationHeader - whether to force passing given token via authorization header\n * @returns A promise of the snapshot and the status code of the response\n */\nexport async function fetchSnapshot(\n snapshotUrl: string,\n token: string | null,\n versionId: string,\n fetchFullSnapshot: boolean,\n forceAccessTokenViaAuthorizationHeader: boolean,\n logger: ITelemetryLogger,\n snapshotDownloader: (url: string, fetchOptions: {[index: string]: any}) => Promise<IOdspResponse<unknown>>,\n): Promise<ISnapshotContents> {\n const path = `/trees/${versionId}`;\n let queryParams: ISnapshotOptions = {};\n\n if (fetchFullSnapshot) {\n if (versionId !== \"latest\") {\n queryParams = { channels: 1, blobs: 2 };\n } else {\n queryParams = { deltas: 1, channels: 1, blobs: 2 };\n }\n }\n\n const queryString = getQueryString(queryParams);\n const { url, headers } = getUrlAndHeadersWithAuth(\n `${snapshotUrl}${path}${queryString}`, token, forceAccessTokenViaAuthorizationHeader);\n const response = await PerformanceEvent.timedExecAsync(\n logger,\n {\n eventName: \"fetchSnapshot\",\n headers: Object.keys(headers).length !== 0 ? true : undefined,\n },\n async () => snapshotDownloader(url, { headers }),\n ) as IOdspResponse<IOdspSnapshot>;\n return convertOdspSnapshotToSnapsohtTreeAndBlobs(response.content);\n}\n\nexport async function fetchSnapshotWithRedeem(\n odspResolvedUrl: IOdspResolvedUrl,\n storageTokenFetcher: InstrumentedStorageTokenFetcher,\n snapshotOptions: ISnapshotOptions | undefined,\n forceAccessTokenViaAuthorizationHeader: boolean,\n logger: ITelemetryLogger,\n snapshotDownloader: (\n finalOdspResolvedUrl: IOdspResolvedUrl,\n storageToken: string,\n snapshotOptions: ISnapshotOptions | undefined,\n controller?: AbortController,\n ) => Promise<ISnapshotRequestAndResponseOptions>,\n putInCache: (valueWithEpoch: IVersionedValueWithEpoch) => Promise<void>,\n removeEntries: () => Promise<void>,\n enableRedeemFallback?: boolean,\n): Promise<ISnapshotContents> {\n // back-compat: This block to be removed with #8784 when we only consume/consider odsp resolvers that are >= 0.51\n const sharingLinkToRedeem = (odspResolvedUrl as any).sharingLinkToRedeem;\n if(sharingLinkToRedeem) {\n odspResolvedUrl.shareLinkInfo = {...odspResolvedUrl.shareLinkInfo, sharingLinkToRedeem}\n }\n\n return fetchLatestSnapshotCore(\n odspResolvedUrl,\n storageTokenFetcher,\n snapshotOptions,\n logger,\n snapshotDownloader,\n putInCache,\n enableRedeemFallback,\n ).catch(async (error) => {\n if (enableRedeemFallback && isRedeemSharingLinkError(odspResolvedUrl, error)) {\n // Execute the redeem fallback\n logger.sendErrorEvent({\n eventName: \"RedeemFallback\",\n errorType: error.errorType,\n }, error);\n await redeemSharingLink(\n odspResolvedUrl, storageTokenFetcher, logger, forceAccessTokenViaAuthorizationHeader);\n const odspResolvedUrlWithoutShareLink: IOdspResolvedUrl =\n { ...odspResolvedUrl,\n shareLinkInfo: {\n ...odspResolvedUrl.shareLinkInfo,\n sharingLinkToRedeem: undefined\n }\n };\n\n return fetchLatestSnapshotCore(\n odspResolvedUrlWithoutShareLink,\n storageTokenFetcher,\n snapshotOptions,\n logger,\n snapshotDownloader,\n putInCache,\n );\n } else {\n throw error;\n }\n }).catch(async (error) => {\n // Clear the cache on 401/403/404 on snapshot fetch from network because this means either the user doesn't\n // have permissions for the file or it was deleted. So, if we do not clear cache, we will continue fetching\n // snapshot from cache in the future.\n if (typeof error === \"object\" && error !== null && error.errorType === DriverErrorType.authorizationError\n || error.errorType === DriverErrorType.fileNotFoundOrAccessDeniedError) {\n await removeEntries();\n }\n throw error;\n });\n}\n\nasync function redeemSharingLink(\n odspResolvedUrl: IOdspResolvedUrl,\n storageTokenFetcher: InstrumentedStorageTokenFetcher,\n logger: ITelemetryLogger,\n forceAccessTokenViaAuthorizationHeader: boolean,\n) {\n return PerformanceEvent.timedExecAsync(\n logger,\n {\n eventName: \"RedeemShareLink\",\n },\n async () => getWithRetryForTokenRefresh(async (tokenFetchOptions) => {\n assert(!!odspResolvedUrl.shareLinkInfo?.sharingLinkToRedeem,\n 0x1ed /* \"Share link should be present\" */);\n const storageToken = await storageTokenFetcher(tokenFetchOptions, \"RedeemShareLink\");\n const encodedShareUrl = getEncodedShareUrl(odspResolvedUrl.shareLinkInfo?.sharingLinkToRedeem);\n const redeemUrl = `${odspResolvedUrl.siteUrl}/_api/v2.0/shares/${encodedShareUrl}`;\n const { url, headers } = getUrlAndHeadersWithAuth(\n redeemUrl, storageToken, forceAccessTokenViaAuthorizationHeader);\n headers.prefer = \"redeemSharingLink\";\n return fetchAndParseAsJSONHelper(url, { headers });\n }),\n );\n}\n\nasync function fetchLatestSnapshotCore(\n odspResolvedUrl: IOdspResolvedUrl,\n storageTokenFetcher: InstrumentedStorageTokenFetcher,\n snapshotOptions: ISnapshotOptions | undefined,\n logger: ITelemetryLogger,\n snapshotDownloader: (\n finalOdspResolvedUrl: IOdspResolvedUrl,\n storageToken: string,\n snapshotOptions: ISnapshotOptions | undefined,\n controller?: AbortController,\n ) => Promise<ISnapshotRequestAndResponseOptions>,\n putInCache: (valueWithEpoch: IVersionedValueWithEpoch) => Promise<void>,\n enableRedeemFallback?: boolean,\n): Promise<ISnapshotContents> {\n return getWithRetryForTokenRefresh(async (tokenFetchOptions) => {\n const storageToken = await storageTokenFetcher(tokenFetchOptions, \"TreesLatest\", true);\n assert(storageToken !== null, 0x1e5 /* \"Storage token should not be null\" */);\n\n let controller: AbortController | undefined;\n if (snapshotOptions?.timeout !== undefined) {\n controller = new AbortController();\n setTimeout(\n () => controller!.abort(),\n snapshotOptions.timeout,\n );\n }\n const perfEvent = {\n eventName: \"TreesLatest\",\n attempts: tokenFetchOptions.refresh ? 2 : 1,\n shareLinkPresent: odspResolvedUrl.shareLinkInfo?.sharingLinkToRedeem !== undefined,\n redeemFallbackEnabled: enableRedeemFallback,\n };\n if (snapshotOptions !== undefined) {\n Object.entries(snapshotOptions).forEach(([key, value]) => {\n if (value !== undefined) {\n perfEvent[`snapshotOption_${key}`] = value;\n }\n });\n }\n // This event measures only successful cases of getLatest call (no tokens, no retries).\n return PerformanceEvent.timedExecAsync(\n logger,\n perfEvent,\n async (event) => {\n const startTime = performance.now();\n const response = await snapshotDownloader(\n odspResolvedUrl,\n storageToken,\n snapshotOptions,\n controller,\n );\n const endTime = performance.now();\n const overallTime = endTime - startTime;\n const snapshot = response.odspSnapshotResponse.content;\n let dnstime: number | undefined; // domainLookupEnd - domainLookupStart\n let redirectTime: number | undefined; // redirectEnd -redirectStart\n let tcpHandshakeTime: number | undefined; // connectEnd - connectStart\n let secureConntime: number | undefined; // connectEnd - secureConnectionStart\n let responseTime: number | undefined; // responsEnd - responseStart\n let fetchStToRespEndTime: number | undefined; // responseEnd - fetchStart\n let reqStToRespEndTime: number | undefined; // responseEnd - requestStart\n let networkTime: number | undefined; // responseEnd - startTime\n const spReqDuration = response.odspSnapshotResponse.headers.get(\"sprequestduration\");\n\n // getEntriesByType is only available in browser performance object\n const resources1 = performance.getEntriesByType?.(\"resource\") ?? [];\n // Usually the latest fetch call is to the end of resources, so we start from the end.\n for (let i = resources1.length - 1; i > 0; i--) {\n const indResTime = resources1[i] as PerformanceResourceTiming;\n const resource_name = indResTime.name;\n const resource_initiatortype = indResTime.initiatorType;\n if ((resource_initiatortype.localeCompare(\"fetch\") === 0)\n && (resource_name.localeCompare(response.requestUrl) === 0)) {\n redirectTime = indResTime.redirectEnd - indResTime.redirectStart;\n dnstime = indResTime.domainLookupEnd - indResTime.domainLookupStart;\n tcpHandshakeTime = indResTime.connectEnd - indResTime.connectStart;\n secureConntime = (indResTime.secureConnectionStart > 0) ?\n (indResTime.connectEnd - indResTime.secureConnectionStart) : 0;\n responseTime = indResTime.responseEnd - indResTime.responseStart;\n fetchStToRespEndTime = (indResTime.fetchStart > 0) ?\n (indResTime.responseEnd - indResTime.fetchStart) : 0;\n reqStToRespEndTime = (indResTime.requestStart > 0) ?\n (indResTime.responseEnd - indResTime.requestStart) : 0;\n networkTime = (indResTime.startTime > 0) ? (indResTime.responseEnd - indResTime.startTime) : 0;\n if (spReqDuration) {\n networkTime = networkTime - parseInt(spReqDuration, 10);\n }\n break;\n }\n }\n\n const { numTrees, numBlobs, encodedBlobsSize } =\n validateAndEvalBlobsAndTrees(response.odspSnapshotResponse.content);\n const clientTime = networkTime ? overallTime - networkTime : undefined;\n\n // There are some scenarios in ODSP where we cannot cache, trees/latest will explicitly tell us when we\n // cannot cache using an HTTP response header.\n const canCache =\n response.odspSnapshotResponse.headers.get(\"disablebrowsercachingofusercontent\") !== \"true\";\n const sequenceNumber: number = snapshot.sequenceNumber ?? 0;\n const seqNumberFromOps = snapshot.ops && snapshot.ops.length > 0 ?\n snapshot.ops[0].sequenceNumber - 1 :\n undefined;\n\n if (!Number.isInteger(sequenceNumber)\n || seqNumberFromOps !== undefined && seqNumberFromOps !== sequenceNumber) {\n logger.sendErrorEvent({ eventName: \"fetchSnapshotError\", sequenceNumber, seqNumberFromOps });\n snapshot.sequenceNumber = undefined;\n } else if (canCache) {\n const fluidEpoch = response.odspSnapshotResponse.headers.get(\"x-fluid-epoch\");\n assert(fluidEpoch !== undefined, 0x1e6 /* \"Epoch should be present in response\" */);\n const value: ISnapshotCachedEntry = {\n ...snapshot,\n cacheEntryTime: Date.now(),\n };\n const valueWithEpoch: IVersionedValueWithEpoch = {\n value,\n fluidEpoch,\n version: persistedCacheValueVersion,\n };\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n putInCache(valueWithEpoch);\n }\n event.end({\n trees: numTrees,\n blobs: snapshot.blobs?.size ?? 0,\n leafNodes: numBlobs,\n encodedBlobsSize,\n sequenceNumber,\n ops: snapshot.ops?.length ?? 0,\n headers: Object.keys(response.requestHeaders).length !== 0 ? true : undefined,\n redirecttime: redirectTime,\n dnsLookuptime: dnstime,\n responsenetworkTime: responseTime,\n tcphandshakeTime: tcpHandshakeTime,\n secureconnectiontime: secureConntime,\n fetchstarttorespendtime: fetchStToRespEndTime,\n reqstarttorespendtime: reqStToRespEndTime,\n overalltime: overallTime,\n networktime: networkTime,\n clienttime: clientTime,\n // Sharing link telemetry regarding sharing link redeem status and performance. Ex: FRL; dur=100,\n // Azure Fluid Relay service; desc=S, FRP; desc=False. Here, FRL is the duration taken for redeem,\n // Azure Fluid Relay service is the redeem status (S means success), and FRP is a flag to indicate\n // if the permission has changed.\n sltelemetry: response.odspSnapshotResponse.headers.get(\"x-fluid-sltelemetry\"),\n ...response.odspSnapshotResponse.commonSpoHeaders,\n });\n return snapshot;\n },\n ).catch((error) => {\n // We hit these errors in stress tests, under load\n // It's useful to try one more time in such case.\n // We might want to add DriverErrorType.offlineError in the future if we see evidence it happens\n // (not in \"real\" offline) and it actually helps.\n if (typeof error === \"object\" && error !== null && (error.errorType === DriverErrorType.fetchFailure ||\n error.errorType === OdspErrorType.fetchTimeout)) {\n error[getWithRetryForTokenRefreshRepeat] = true;\n }\n throw error;\n });\n });\n}\n\ninterface ISnapshotRequestAndResponseOptions {\n odspSnapshotResponse: IOdspResponse<ISnapshotContents>,\n requestUrl: string,\n requestHeaders: {[index: string]: any},\n}\n\n/**\n * This function fetches the older snapshot format which is the json format(IOdspSnapshot).\n * @param odspResolvedUrl - resolved odsp url.\n * @param storageToken - token to do the auth for network request.\n * @param snapshotOptions - Options used to specify how and what to fetch in the snapshot.\n * @param controller - abort controller if caller needs to abort the network call.\n * @param epochTracker - epoch tracker used to add/validate epoch in the network call.\n * @returns fetched snapshot.\n */\nasync function fetchSnapshotContentsCoreV1(\n odspResolvedUrl: IOdspResolvedUrl,\n storageToken: string,\n snapshotOptions: ISnapshotOptions | undefined,\n controller?: AbortController,\n epochTracker?: EpochTracker,\n): Promise<ISnapshotRequestAndResponseOptions> {\n const snapshotUrl = odspResolvedUrl.endpoints.snapshotStorageUrl;\n const url = `${snapshotUrl}/trees/latest?ump=1`;\n const { body, headers } = getFormBodyAndHeaders(odspResolvedUrl, storageToken, snapshotOptions);\n const fetchOptions = {\n body,\n headers,\n signal: controller?.signal,\n method: \"POST\",\n };\n const response = await (epochTracker?.fetchAndParseAsJSON<IOdspSnapshot>(url, fetchOptions, \"treesLatest\", true) ??\n fetchAndParseAsJSONHelper<IOdspSnapshot>(url, fetchOptions));\n const snapshotContents: ISnapshotContents = convertOdspSnapshotToSnapsohtTreeAndBlobs(response.content);\n const finalSnapshotContents: IOdspResponse<ISnapshotContents> = { ...response, content: snapshotContents };\n return {\n odspSnapshotResponse: finalSnapshotContents,\n requestHeaders: headers,\n requestUrl: url,\n };\n}\n\n/**\n * This function fetches the binary compact snapshot format. This is an experimental feature\n * and is behind a feature flag.\n * @param odspResolvedUrl - resolved odsp url.\n * @param storageToken - token to do the auth for network request.\n * @param snapshotOptions - Options used to specify how and what to fetch in the snapshot.\n * @param controller - abort controller if caller needs to abort the network call.\n * @param epochTracker - epoch tracker used to add/validate epoch in the network call.\n * @returns fetched snapshot.\n */\nasync function fetchSnapshotContentsCoreV2(\n odspResolvedUrl: IOdspResolvedUrl,\n storageToken: string,\n snapshotOptions: ISnapshotOptions | undefined,\n controller?: AbortController,\n epochTracker?: EpochTracker,\n): Promise<ISnapshotRequestAndResponseOptions> {\n const fullUrl = `${odspResolvedUrl.siteUrl}/_api/v2.1/drives/${odspResolvedUrl.driveId}/items/${\n odspResolvedUrl.itemId}/opStream/attachments/latest/content?ump=1`;\n\n const { body, headers } = getFormBodyAndHeaders(odspResolvedUrl, storageToken, snapshotOptions);\n const fetchOptions = {\n body,\n headers,\n signal: controller?.signal,\n method: \"POST\",\n };\n\n const response = await (epochTracker?.fetchArray(fullUrl, fetchOptions, \"treesLatest\", true) ??\n fetchArray(fullUrl, fetchOptions));\n const snapshotContents: ISnapshotContents = parseCompactSnapshotResponse(\n new ReadBuffer(new Uint8Array(response.content)));\n const finalSnapshotContents: IOdspResponse<ISnapshotContents> = { ...response, content: snapshotContents };\n return {\n odspSnapshotResponse: finalSnapshotContents,\n requestHeaders: headers,\n requestUrl: fullUrl,\n };\n}\n\nfunction getFormBodyAndHeaders(\n odspResolvedUrl: IOdspResolvedUrl,\n storageToken: string,\n snapshotOptions: ISnapshotOptions | undefined,\n) {\n const formBoundary = uuid();\n const formParams: string[] = [];\n formParams.push(`--${formBoundary}`);\n formParams.push(`Authorization: Bearer ${storageToken}`);\n formParams.push(`X-HTTP-Method-Override: GET`);\n if (snapshotOptions !== undefined) {\n Object.entries(snapshotOptions).forEach(([key, value]) => {\n if (value !== undefined) {\n formParams.push(`${key}: ${value}`);\n }\n });\n }\n if (odspResolvedUrl.shareLinkInfo?.sharingLinkToRedeem) {\n formParams.push(`sl: ${odspResolvedUrl.shareLinkInfo?.sharingLinkToRedeem}`);\n }\n formParams.push(`_post: 1`);\n formParams.push(`\\r\\n--${formBoundary}--`);\n const postBody = formParams.join(\"\\r\\n\");\n const headers: {[index: string]: any} = {\n \"Content-Type\": `multipart/form-data;boundary=${formBoundary}`,\n };\n return { body: postBody, headers };\n}\n\nfunction validateAndEvalBlobsAndTrees(snapshot: ISnapshotContents) {\n assert(snapshot.snapshotTree !== undefined,\n 0x200 /* \"Returned odsp snapshot is malformed. No trees!\" */);\n assert(snapshot.blobs !== undefined,\n 0x201 /* \"Returned odsp snapshot is malformed. No blobs!\" */);\n const numTrees = countTreesInSnapshotTree(snapshot.snapshotTree);\n const numBlobs = snapshot.blobs.size;\n let encodedBlobsSize = 0;\n for (const [_, blobContent] of snapshot.blobs) {\n encodedBlobsSize += blobContent.byteLength;\n }\n return { numTrees, numBlobs, encodedBlobsSize };\n}\n\nfunction countTreesInSnapshotTree(snapshotTree: ISnapshotTree): number {\n let numTrees = 0;\n for (const [_, tree] of Object.entries(snapshotTree.trees)) {\n numTrees += 1;\n numTrees += countTreesInSnapshotTree(tree);\n }\n return numTrees;\n}\n\nexport async function downloadSnapshot(\n odspResolvedUrl: IOdspResolvedUrl,\n storageToken: string,\n logger: ITelemetryLogger,\n snapshotOptions: ISnapshotOptions | undefined,\n fetchBinarySnapshotFormat?: boolean,\n controller?: AbortController,\n epochTracker?: EpochTracker,\n): Promise<ISnapshotRequestAndResponseOptions> {\n // back-compat: This block to be removed with #8784 when we only consume/consider odsp resolvers that are >= 0.51\n const sharingLinkToRedeem = (odspResolvedUrl as any).sharingLinkToRedeem;\n if(sharingLinkToRedeem) {\n odspResolvedUrl.shareLinkInfo = {...odspResolvedUrl.shareLinkInfo, sharingLinkToRedeem}\n }\n\n if (fetchBinarySnapshotFormat) {\n // Logging an event here as it is not supposed to be used in production yet and only in experimental mode.\n logger.sendTelemetryEvent({ eventName: \"BinarySnapshotFetched\" });\n return fetchSnapshotContentsCoreV2(odspResolvedUrl, storageToken, snapshotOptions, controller, epochTracker);\n } else {\n return fetchSnapshotContentsCoreV1(odspResolvedUrl, storageToken, snapshotOptions, controller, epochTracker);\n }\n}\n\nfunction isRedeemSharingLinkError(odspResolvedUrl: IOdspResolvedUrl, error: any) {\n if (odspResolvedUrl.shareLinkInfo?.sharingLinkToRedeem !== undefined\n && (typeof error === \"object\" && error !== null)\n && (error.errorType === DriverErrorType.authorizationError\n || error.errorType === DriverErrorType.fileNotFoundOrAccessDeniedError)) {\n return true;\n }\n return false;\n}\n\nfunction getEncodedShareUrl(url: string): string {\n /**\n * Encode the url to accepted format by Sharepoint\n * https://docs.microsoft.com/en-us/onedrive/developer/rest-api/api/shares_get\n */\n let encodedUrl = fromUtf8ToBase64(encodeURI(url));\n encodedUrl = encodedUrl\n .replace(/=+$/g, \"\")\n .replace(/\\//g, \"_\")\n .replace(/\\+/g, \"-\");\n encodedUrl = \"u!\".concat(encodedUrl);\n return encodedUrl;\n}\n"]}
|
package/lib/getFileLink.js
CHANGED
|
@@ -63,7 +63,7 @@ export async function getFileLink(getToken, odspUrlParts, identityType, logger)
|
|
|
63
63
|
return fileLink;
|
|
64
64
|
}
|
|
65
65
|
async function getFileLinkCore(getToken, odspUrlParts, identityType, logger) {
|
|
66
|
-
const fileItem = await getFileItemLite(getToken, odspUrlParts, logger);
|
|
66
|
+
const fileItem = await getFileItemLite(getToken, odspUrlParts, logger, identityType === "Consumer");
|
|
67
67
|
// ODC canonical link does not require any additional processing
|
|
68
68
|
if (identityType === "Consumer") {
|
|
69
69
|
return fileItem.webUrl;
|
|
@@ -76,7 +76,7 @@ async function getFileLinkCore(getToken, odspUrlParts, identityType, logger) {
|
|
|
76
76
|
var _a;
|
|
77
77
|
attempts++;
|
|
78
78
|
const token = await getToken(Object.assign(Object.assign({}, options), odspUrlParts));
|
|
79
|
-
const { url, headers } = getUrlAndHeadersWithAuth(`${odspUrlParts.siteUrl}/_api/web/GetFileByUrl(@a1)/ListItemAllFields/GetSharingInformation?@a1=${encodeURIComponent(`'${fileItem.webDavUrl}'`)}`, tokenFromResponse(token));
|
|
79
|
+
const { url, headers } = getUrlAndHeadersWithAuth(`${odspUrlParts.siteUrl}/_api/web/GetFileByUrl(@a1)/ListItemAllFields/GetSharingInformation?@a1=${encodeURIComponent(`'${fileItem.webDavUrl}'`)}`, tokenFromResponse(token), false);
|
|
80
80
|
const requestInit = {
|
|
81
81
|
method: "POST",
|
|
82
82
|
headers: Object.assign({ "Content-Type": "application/json;odata=verbose", "Accept": "application/json;odata=verbose" }, headers),
|
|
@@ -101,7 +101,7 @@ const isFileItemLite = (maybeFileItemLite) => {
|
|
|
101
101
|
}
|
|
102
102
|
return true;
|
|
103
103
|
};
|
|
104
|
-
async function getFileItemLite(getToken, odspUrlParts, logger) {
|
|
104
|
+
async function getFileItemLite(getToken, odspUrlParts, logger, forceAccessTokenViaAuthorizationHeader) {
|
|
105
105
|
return PerformanceEvent.timedExecAsync(logger, { eventName: "odspFileLink", requestName: "getFileItemLite" }, async (event) => {
|
|
106
106
|
let attempts = 0;
|
|
107
107
|
let additionalProps;
|
|
@@ -109,7 +109,7 @@ async function getFileItemLite(getToken, odspUrlParts, logger) {
|
|
|
109
109
|
attempts++;
|
|
110
110
|
const { siteUrl, driveId, itemId } = odspUrlParts;
|
|
111
111
|
const token = await getToken(Object.assign(Object.assign({}, options), { siteUrl, driveId, itemId }));
|
|
112
|
-
const { url, headers } = getUrlAndHeadersWithAuth(`${siteUrl}/_api/v2.0/drives/${driveId}/items/${itemId}?select=webUrl,webDavUrl`, tokenFromResponse(token));
|
|
112
|
+
const { url, headers } = getUrlAndHeadersWithAuth(`${siteUrl}/_api/v2.0/drives/${driveId}/items/${itemId}?select=webUrl,webDavUrl`, tokenFromResponse(token), forceAccessTokenViaAuthorizationHeader);
|
|
113
113
|
const requestInit = { method: "GET", headers };
|
|
114
114
|
const response = await fetchHelper(url, requestInit);
|
|
115
115
|
additionalProps = response.commonSpoHeaders;
|
package/lib/getFileLink.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getFileLink.js","sourceRoot":"","sources":["../src/getFileLink.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { assert, delay } from \"@fluidframework/common-utils\";\nimport { canRetryOnError, getRetryDelayFromError, NonRetryableError } from \"@fluidframework/driver-utils\";\nimport { PerformanceEvent } from \"@fluidframework/telemetry-utils\";\nimport { DriverErrorType } from \"@fluidframework/driver-definitions\";\nimport {\n IOdspUrlParts,\n OdspResourceTokenFetchOptions,\n IdentityType,\n TokenFetcher,\n tokenFromResponse,\n} from \"@fluidframework/odsp-driver-definitions\";\nimport { getUrlAndHeadersWithAuth } from \"./getUrlAndHeadersWithAuth\";\nimport { fetchHelper, getWithRetryForTokenRefresh } from \"./odspUtils\";\n\n// Store cached responses for the lifetime of web session as file link remains the same for given file item\nconst fileLinkCache = new Map<string, Promise<string>>();\n\n/**\n * Returns file link for a file with given drive and item ids.\n * Scope needed: files.readwrite.all.\n * This function keeps retrying if it gets a retriable error or wait for some delay if it gets a\n * throttling error. In future, we are thinking of app allowing to pass some cancel token, with which\n * we would be able to stop retrying.\n * @param getToken - used to fetch access tokens needed to execute operation\n * @param siteUrl - url of the site that contains the file\n * @param driveId - drive where file is stored\n * @param itemId - file id\n * @param identityType - type of client account\n * @param logger - used to log results of operation, including any error\n * @returns Promise which resolves to file link url when successful; otherwise, undefined.\n */\nexport async function getFileLink(\n getToken: TokenFetcher<OdspResourceTokenFetchOptions>,\n odspUrlParts: IOdspUrlParts,\n identityType: IdentityType,\n logger: ITelemetryLogger,\n): Promise<string> {\n const cacheKey = `${odspUrlParts.siteUrl}_${odspUrlParts.driveId}_${odspUrlParts.itemId}`;\n const maybeFileLinkCacheEntry = fileLinkCache.get(cacheKey);\n if (maybeFileLinkCacheEntry !== undefined) {\n return maybeFileLinkCacheEntry;\n }\n\n const valueGenerator = async function() {\n let result: string | undefined;\n let success = false;\n let retryAfterMs = 1000;\n do {\n try {\n result = await getFileLinkCore(getToken, odspUrlParts, identityType, logger);\n success = true;\n } catch (err) {\n // If it is not retriable, then just throw\n if (!canRetryOnError(err)) {\n // Delete from the cache to permit retrying later.\n fileLinkCache.delete(cacheKey);\n throw err;\n }\n // If the error is throttling error, then wait for the specified time before retrying.\n // If the waitTime is not specified, then we start with retrying immediately to max of 8s.\n retryAfterMs = getRetryDelayFromError(err) ?? Math.min(retryAfterMs * 2, 8000);\n await delay(retryAfterMs);\n }\n } while (!success);\n\n // We are guaranteed to run the getFileLinkCore at least once with successful result (which must be a string)\n assert(result !== undefined, 0x292 /* \"Unexpected undefined result from getFileLinkCore\" */);\n return result;\n };\n const fileLink = valueGenerator();\n fileLinkCache.set(cacheKey, fileLink);\n return fileLink;\n}\n\nasync function getFileLinkCore(\n getToken: TokenFetcher<OdspResourceTokenFetchOptions>,\n odspUrlParts: IOdspUrlParts,\n identityType: IdentityType,\n logger: ITelemetryLogger,\n): Promise<string> {\n const fileItem = await getFileItemLite(getToken, odspUrlParts, logger);\n\n // ODC canonical link does not require any additional processing\n if (identityType === \"Consumer\") {\n return fileItem.webUrl;\n }\n\n // ODSP link requires extra call to return link that is resistant to file being renamed or moved to different folder\n return PerformanceEvent.timedExecAsync(\n logger,\n { eventName: \"odspFileLink\", requestName: \"getSharingInformation\" },\n async (event) => {\n let attempts = 0;\n let additionalProps;\n const fileLink = await getWithRetryForTokenRefresh(async (options) => {\n attempts++;\n const token = await getToken({ ...options, ... odspUrlParts });\n const { url, headers } = getUrlAndHeadersWithAuth(\n `${odspUrlParts.siteUrl}/_api/web/GetFileByUrl(@a1)/ListItemAllFields/GetSharingInformation?@a1=${\n encodeURIComponent(`'${fileItem.webDavUrl}'`)\n }`, tokenFromResponse(token));\n const requestInit = {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json;odata=verbose\",\n \"Accept\": \"application/json;odata=verbose\",\n ...headers,\n },\n };\n const response = await fetchHelper(url, requestInit);\n additionalProps = response.commonSpoHeaders;\n\n const sharingInfo = await response.content.json();\n const directUrl = sharingInfo?.d?.directUrl;\n if (typeof directUrl !== \"string\") {\n // This will retry once in getWithRetryForTokenRefresh\n throw new NonRetryableError(\n \"getFileLinkCoreMalformedResponse\",\n \"Malformed GetSharingInformation response\",\n DriverErrorType.incorrectServerResponse);\n }\n return directUrl;\n });\n event.end({ ...additionalProps, attempts });\n return fileLink;\n },\n );\n}\n\n/**\n * This represents a lite version of file item containing only the webUrl and webDavUrl properties\n */\ninterface FileItemLite {\n webUrl: string;\n webDavUrl: string;\n}\n\nconst isFileItemLite = (maybeFileItemLite: any): maybeFileItemLite is FileItemLite => {\n if (typeof maybeFileItemLite.webUrl !== \"string\" || typeof maybeFileItemLite.webDavUrl !== \"string\") {\n return false;\n }\n return true;\n};\n\nasync function getFileItemLite(\n getToken: TokenFetcher<OdspResourceTokenFetchOptions>,\n odspUrlParts: IOdspUrlParts,\n logger: ITelemetryLogger,\n): Promise<FileItemLite> {\n return PerformanceEvent.timedExecAsync(\n logger,\n { eventName: \"odspFileLink\", requestName: \"getFileItemLite\" },\n async (event) => {\n let attempts = 0;\n let additionalProps;\n const fileItem = await getWithRetryForTokenRefresh(async (options) => {\n attempts++;\n const {siteUrl, driveId, itemId} = odspUrlParts;\n const token = await getToken({ ...options, siteUrl, driveId, itemId});\n const { url, headers } = getUrlAndHeadersWithAuth(\n `${siteUrl}/_api/v2.0/drives/${driveId}/items/${itemId}?select=webUrl,webDavUrl`,\n tokenFromResponse(token),\n );\n const requestInit = { method: \"GET\", headers };\n const response = await fetchHelper(url, requestInit);\n additionalProps = response.commonSpoHeaders;\n\n const responseJson = await response.content.json();\n if (!isFileItemLite(responseJson)) {\n // This will retry once in getWithRetryForTokenRefresh\n throw new NonRetryableError(\n \"getFileItemLiteMalformedResponse\",\n \"Malformed getFileItemLite response\",\n DriverErrorType.incorrectServerResponse);\n }\n return responseJson;\n });\n event.end({ ...additionalProps, attempts });\n return fileItem;\n },\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"getFileLink.js","sourceRoot":"","sources":["../src/getFileLink.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { assert, delay } from \"@fluidframework/common-utils\";\nimport { canRetryOnError, getRetryDelayFromError, NonRetryableError } from \"@fluidframework/driver-utils\";\nimport { PerformanceEvent } from \"@fluidframework/telemetry-utils\";\nimport { DriverErrorType } from \"@fluidframework/driver-definitions\";\nimport {\n IOdspUrlParts,\n OdspResourceTokenFetchOptions,\n IdentityType,\n TokenFetcher,\n tokenFromResponse,\n} from \"@fluidframework/odsp-driver-definitions\";\nimport { getUrlAndHeadersWithAuth } from \"./getUrlAndHeadersWithAuth\";\nimport { fetchHelper, getWithRetryForTokenRefresh } from \"./odspUtils\";\n\n// Store cached responses for the lifetime of web session as file link remains the same for given file item\nconst fileLinkCache = new Map<string, Promise<string>>();\n\n/**\n * Returns file link for a file with given drive and item ids.\n * Scope needed: files.readwrite.all.\n * This function keeps retrying if it gets a retriable error or wait for some delay if it gets a\n * throttling error. In future, we are thinking of app allowing to pass some cancel token, with which\n * we would be able to stop retrying.\n * @param getToken - used to fetch access tokens needed to execute operation\n * @param siteUrl - url of the site that contains the file\n * @param driveId - drive where file is stored\n * @param itemId - file id\n * @param identityType - type of client account\n * @param logger - used to log results of operation, including any error\n * @returns Promise which resolves to file link url when successful; otherwise, undefined.\n */\nexport async function getFileLink(\n getToken: TokenFetcher<OdspResourceTokenFetchOptions>,\n odspUrlParts: IOdspUrlParts,\n identityType: IdentityType,\n logger: ITelemetryLogger,\n): Promise<string> {\n const cacheKey = `${odspUrlParts.siteUrl}_${odspUrlParts.driveId}_${odspUrlParts.itemId}`;\n const maybeFileLinkCacheEntry = fileLinkCache.get(cacheKey);\n if (maybeFileLinkCacheEntry !== undefined) {\n return maybeFileLinkCacheEntry;\n }\n\n const valueGenerator = async function() {\n let result: string | undefined;\n let success = false;\n let retryAfterMs = 1000;\n do {\n try {\n result = await getFileLinkCore(getToken, odspUrlParts, identityType, logger);\n success = true;\n } catch (err) {\n // If it is not retriable, then just throw\n if (!canRetryOnError(err)) {\n // Delete from the cache to permit retrying later.\n fileLinkCache.delete(cacheKey);\n throw err;\n }\n // If the error is throttling error, then wait for the specified time before retrying.\n // If the waitTime is not specified, then we start with retrying immediately to max of 8s.\n retryAfterMs = getRetryDelayFromError(err) ?? Math.min(retryAfterMs * 2, 8000);\n await delay(retryAfterMs);\n }\n } while (!success);\n\n // We are guaranteed to run the getFileLinkCore at least once with successful result (which must be a string)\n assert(result !== undefined, 0x292 /* \"Unexpected undefined result from getFileLinkCore\" */);\n return result;\n };\n const fileLink = valueGenerator();\n fileLinkCache.set(cacheKey, fileLink);\n return fileLink;\n}\n\nasync function getFileLinkCore(\n getToken: TokenFetcher<OdspResourceTokenFetchOptions>,\n odspUrlParts: IOdspUrlParts,\n identityType: IdentityType,\n logger: ITelemetryLogger,\n): Promise<string> {\n const fileItem = await getFileItemLite(getToken, odspUrlParts, logger, identityType === \"Consumer\");\n\n // ODC canonical link does not require any additional processing\n if (identityType === \"Consumer\") {\n return fileItem.webUrl;\n }\n\n // ODSP link requires extra call to return link that is resistant to file being renamed or moved to different folder\n return PerformanceEvent.timedExecAsync(\n logger,\n { eventName: \"odspFileLink\", requestName: \"getSharingInformation\" },\n async (event) => {\n let attempts = 0;\n let additionalProps;\n const fileLink = await getWithRetryForTokenRefresh(async (options) => {\n attempts++;\n const token = await getToken({ ...options, ... odspUrlParts });\n const { url, headers } = getUrlAndHeadersWithAuth(\n `${odspUrlParts.siteUrl}/_api/web/GetFileByUrl(@a1)/ListItemAllFields/GetSharingInformation?@a1=${\n encodeURIComponent(`'${fileItem.webDavUrl}'`)\n }`,\n tokenFromResponse(token),\n false,\n );\n const requestInit = {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json;odata=verbose\",\n \"Accept\": \"application/json;odata=verbose\",\n ...headers,\n },\n };\n const response = await fetchHelper(url, requestInit);\n additionalProps = response.commonSpoHeaders;\n\n const sharingInfo = await response.content.json();\n const directUrl = sharingInfo?.d?.directUrl;\n if (typeof directUrl !== \"string\") {\n // This will retry once in getWithRetryForTokenRefresh\n throw new NonRetryableError(\n \"getFileLinkCoreMalformedResponse\",\n \"Malformed GetSharingInformation response\",\n DriverErrorType.incorrectServerResponse);\n }\n return directUrl;\n });\n event.end({ ...additionalProps, attempts });\n return fileLink;\n },\n );\n}\n\n/**\n * This represents a lite version of file item containing only the webUrl and webDavUrl properties\n */\ninterface FileItemLite {\n webUrl: string;\n webDavUrl: string;\n}\n\nconst isFileItemLite = (maybeFileItemLite: any): maybeFileItemLite is FileItemLite => {\n if (typeof maybeFileItemLite.webUrl !== \"string\" || typeof maybeFileItemLite.webDavUrl !== \"string\") {\n return false;\n }\n return true;\n};\n\nasync function getFileItemLite(\n getToken: TokenFetcher<OdspResourceTokenFetchOptions>,\n odspUrlParts: IOdspUrlParts,\n logger: ITelemetryLogger,\n forceAccessTokenViaAuthorizationHeader: boolean,\n): Promise<FileItemLite> {\n return PerformanceEvent.timedExecAsync(\n logger,\n { eventName: \"odspFileLink\", requestName: \"getFileItemLite\" },\n async (event) => {\n let attempts = 0;\n let additionalProps;\n const fileItem = await getWithRetryForTokenRefresh(async (options) => {\n attempts++;\n const {siteUrl, driveId, itemId} = odspUrlParts;\n const token = await getToken({ ...options, siteUrl, driveId, itemId});\n const { url, headers } = getUrlAndHeadersWithAuth(\n `${siteUrl}/_api/v2.0/drives/${driveId}/items/${itemId}?select=webUrl,webDavUrl`,\n tokenFromResponse(token),\n forceAccessTokenViaAuthorizationHeader,\n );\n const requestInit = { method: \"GET\", headers };\n const response = await fetchHelper(url, requestInit);\n additionalProps = response.commonSpoHeaders;\n\n const responseJson = await response.content.json();\n if (!isFileItemLite(responseJson)) {\n // This will retry once in getWithRetryForTokenRefresh\n throw new NonRetryableError(\n \"getFileItemLiteMalformedResponse\",\n \"Malformed getFileItemLite response\",\n DriverErrorType.incorrectServerResponse);\n }\n return responseJson;\n });\n event.end({ ...additionalProps, attempts });\n return fileItem;\n },\n );\n}\n"]}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
|
-
export declare function getUrlAndHeadersWithAuth(url: string, token: string | null): {
|
|
5
|
+
export declare function getUrlAndHeadersWithAuth(url: string, token: string | null, forceAccessTokenViaAuthorizationHeader: boolean): {
|
|
6
6
|
url: string;
|
|
7
7
|
headers: {
|
|
8
8
|
[index: string]: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getUrlAndHeadersWithAuth.d.ts","sourceRoot":"","sources":["../src/getUrlAndHeadersWithAuth.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"getUrlAndHeadersWithAuth.d.ts","sourceRoot":"","sources":["../src/getUrlAndHeadersWithAuth.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,wBAAgB,wBAAwB,CACpC,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,GAAG,IAAI,EACpB,sCAAsC,EAAE,OAAO,GAChD;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE;QAAE,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAA;CAAE,CAgCvD"}
|
|
@@ -2,42 +2,29 @@
|
|
|
2
2
|
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
|
-
|
|
6
|
-
* Gets the length of the query string portion of a url.
|
|
7
|
-
* @param url The full url
|
|
8
|
-
*/
|
|
9
|
-
function getQueryStringLength(url) {
|
|
10
|
-
const queryParamStart = url.indexOf("?");
|
|
11
|
-
if (queryParamStart === -1) {
|
|
12
|
-
return 0;
|
|
13
|
-
}
|
|
14
|
-
return url.length - queryParamStart - 1;
|
|
15
|
-
}
|
|
16
|
-
// eslint-disable-next-line max-len
|
|
17
|
-
export function getUrlAndHeadersWithAuth(url, token) {
|
|
5
|
+
export function getUrlAndHeadersWithAuth(url, token, forceAccessTokenViaAuthorizationHeader) {
|
|
18
6
|
if (!token || token.length === 0) {
|
|
19
7
|
return { url, headers: {} };
|
|
20
8
|
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
//
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
};
|
|
9
|
+
if (!forceAccessTokenViaAuthorizationHeader) {
|
|
10
|
+
// Pass access token via query string: this will make request be treated as 'simple' request
|
|
11
|
+
// which does not require OPTIONS call as part of CORS check.
|
|
12
|
+
const urlWithAccessTokenInQueryString = new URL(url);
|
|
13
|
+
// IMPORTANT: Do not apply encodeURIComponent to token, param value is automatically encoded
|
|
14
|
+
// when set via URLSearchParams class
|
|
15
|
+
urlWithAccessTokenInQueryString.searchParams.set("access_token", token);
|
|
16
|
+
// ODSP APIs have a limitation that the query string cannot exceed 2048 characters.
|
|
17
|
+
// If the query string exceeds 2048, we have to fall back to sending the access token as a header, which
|
|
18
|
+
// has a negative performance implication as it adds a performance overhead.
|
|
19
|
+
// NOTE: URL.search.length value includes '?' symbol and it is unclear whether backend logic which enforces
|
|
20
|
+
// query length limit accounts for it. This logic errs on side of caution and includes that key in overall
|
|
21
|
+
// query length.
|
|
22
|
+
if (urlWithAccessTokenInQueryString.search.length <= 2048) {
|
|
23
|
+
return {
|
|
24
|
+
headers: {},
|
|
25
|
+
url: urlWithAccessTokenInQueryString.href,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
41
28
|
}
|
|
42
29
|
return {
|
|
43
30
|
headers: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getUrlAndHeadersWithAuth.js","sourceRoot":"","sources":["../src/getUrlAndHeadersWithAuth.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH
|
|
1
|
+
{"version":3,"file":"getUrlAndHeadersWithAuth.js","sourceRoot":"","sources":["../src/getUrlAndHeadersWithAuth.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,UAAU,wBAAwB,CACpC,GAAW,EACX,KAAoB,EACpB,sCAA+C;IAE/C,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE;QAC9B,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;KAC/B;IAED,IAAI,CAAC,sCAAsC,EAAE;QACzC,4FAA4F;QAC5F,6DAA6D;QAC7D,MAAM,+BAA+B,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;QACrD,4FAA4F;QAC5F,qCAAqC;QACrC,+BAA+B,CAAC,YAAY,CAAC,GAAG,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;QACxE,mFAAmF;QACnF,wGAAwG;QACxG,4EAA4E;QAC5E,2GAA2G;QAC3G,0GAA0G;QAC1G,gBAAgB;QAChB,IAAI,+BAA+B,CAAC,MAAM,CAAC,MAAM,IAAI,IAAI,EAAE;YACvD,OAAO;gBACH,OAAO,EAAE,EAAE;gBACX,GAAG,EAAE,+BAA+B,CAAC,IAAI;aAC5C,CAAC;SACL;KACJ;IAED,OAAO;QACH,OAAO,EAAE;YACL,aAAa,EAAE,UAAU,KAAK,EAAE;SACnC;QACD,GAAG;KACN,CAAC;AACN,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport function getUrlAndHeadersWithAuth(\n url: string,\n token: string | null,\n forceAccessTokenViaAuthorizationHeader: boolean,\n): { url: string, headers: { [index: string]: string } } {\n if (!token || token.length === 0) {\n return { url, headers: {} };\n }\n\n if (!forceAccessTokenViaAuthorizationHeader) {\n // Pass access token via query string: this will make request be treated as 'simple' request\n // which does not require OPTIONS call as part of CORS check.\n const urlWithAccessTokenInQueryString = new URL(url);\n // IMPORTANT: Do not apply encodeURIComponent to token, param value is automatically encoded\n // when set via URLSearchParams class\n urlWithAccessTokenInQueryString.searchParams.set(\"access_token\", token);\n // ODSP APIs have a limitation that the query string cannot exceed 2048 characters.\n // If the query string exceeds 2048, we have to fall back to sending the access token as a header, which\n // has a negative performance implication as it adds a performance overhead.\n // NOTE: URL.search.length value includes '?' symbol and it is unclear whether backend logic which enforces\n // query length limit accounts for it. This logic errs on side of caution and includes that key in overall\n // query length.\n if (urlWithAccessTokenInQueryString.search.length <= 2048) {\n return {\n headers: {},\n url: urlWithAccessTokenInQueryString.href,\n };\n }\n }\n\n return {\n headers: {\n Authorization: `Bearer ${token}`,\n },\n url,\n };\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"odspDeltaStorageService.d.ts","sourceRoot":"","sources":["../src/odspDeltaStorageService.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,oCAAoC,CAAC;AAE5F,OAAO,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAC;AACjF,OAAO,EAAE,+BAA+B,EAAE,MAAM,yCAAyC,CAAC;AAC1F,OAAO,EAAE,kBAAkB,EAAE,4BAA4B,EAAE,MAAM,oCAAoC,CAAC;AAMtG,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAG9C;;GAEG;AACH,qBAAa,uBAAuB;IAE5B,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAHN,YAAY,EAAE,MAAM,EACpB,eAAe,EAAE,+BAA+B,EAChD,YAAY,EAAE,YAAY,EAC1B,MAAM,EAAE,gBAAgB;IAI7C;;;;;;OAMG;IACW,GAAG,CACb,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,EACV,cAAc,EAAE,oBAAoB,EACpC,WAAW,CAAC,EAAE,MAAM,GACrB,OAAO,CAAC,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"odspDeltaStorageService.d.ts","sourceRoot":"","sources":["../src/odspDeltaStorageService.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,oCAAoC,CAAC;AAE5F,OAAO,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAC;AACjF,OAAO,EAAE,+BAA+B,EAAE,MAAM,yCAAyC,CAAC;AAC1F,OAAO,EAAE,kBAAkB,EAAE,4BAA4B,EAAE,MAAM,oCAAoC,CAAC;AAMtG,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAG9C;;GAEG;AACH,qBAAa,uBAAuB;IAE5B,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAHN,YAAY,EAAE,MAAM,EACpB,eAAe,EAAE,+BAA+B,EAChD,YAAY,EAAE,YAAY,EAC1B,MAAM,EAAE,gBAAgB;IAI7C;;;;;;OAMG;IACW,GAAG,CACb,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,EACV,cAAc,EAAE,oBAAoB,EACpC,WAAW,CAAC,EAAE,MAAM,GACrB,OAAO,CAAC,kBAAkB,CAAC;IAiEvB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM;CAK3C;AAED,qBAAa,yBAA0B,YAAW,4BAA4B;IAItE,OAAO,CAAC,WAAW;IACnB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,cAAc;IAK/B,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAClC,OAAO,CAAC,QAAQ,CAAC,WAAW;IAdhC,OAAO,CAAC,cAAc,CAA2B;gBAGrC,WAAW,EAAE,yBAAyB,EAAE,GAAG,SAAS,EAC3C,MAAM,EAAE,gBAAgB,EACxB,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,EACnB,cAAc,EAAE,CAC7B,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,EACV,cAAc,EAAE,oBAAoB,EACpC,WAAW,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,kBAAkB,CAAC,EACvC,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,yBAAyB,EAAE,CAAC,EAC7E,iBAAiB,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,KAAK,IAAI,EACrD,WAAW,EAAE,CAAC,GAAG,EAAE,yBAAyB,EAAE,KAAK,IAAI;IAI5E,SAAS,CAAC,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,yBAAyB,EAAE,EAAE,IAAI,EAAE,MAAM;IAiBvF,aAAa,CAChB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,WAAW,CAAC,EAAE,WAAW,EACzB,UAAU,CAAC,EAAE,OAAO,EACpB,WAAW,CAAC,EAAE,MAAM;CAmF3B"}
|
|
@@ -34,9 +34,6 @@ export class OdspDeltaStorageService {
|
|
|
34
34
|
let postBody = `--${formBoundary}\r\n`;
|
|
35
35
|
postBody += `Authorization: Bearer ${storageToken}\r\n`;
|
|
36
36
|
postBody += `X-HTTP-Method-Override: GET\r\n`;
|
|
37
|
-
if (fetchReason !== undefined) {
|
|
38
|
-
postBody += `fetchReason: ${fetchReason}\r\n`;
|
|
39
|
-
}
|
|
40
37
|
postBody += `_post: 1\r\n`;
|
|
41
38
|
postBody += `\r\n--${formBoundary}--`;
|
|
42
39
|
const headers = {
|
|
@@ -54,7 +51,7 @@ export class OdspDeltaStorageService {
|
|
|
54
51
|
body: postBody,
|
|
55
52
|
method: "POST",
|
|
56
53
|
signal: abort.signal,
|
|
57
|
-
}, "ops", true);
|
|
54
|
+
}, "ops", true, fetchReason);
|
|
58
55
|
clearTimeout(timer);
|
|
59
56
|
const deltaStorageResponse = response.content;
|
|
60
57
|
let messages;
|