@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/src/createFile.ts
CHANGED
|
@@ -55,6 +55,7 @@ export async function createNewFluidFile(
|
|
|
55
55
|
epochTracker: EpochTracker,
|
|
56
56
|
fileEntry: IFileEntry,
|
|
57
57
|
createNewCaching: boolean,
|
|
58
|
+
forceAccessTokenViaAuthorizationHeader: boolean,
|
|
58
59
|
): Promise<IOdspResolvedUrl> {
|
|
59
60
|
// Check for valid filename before the request to create file is actually made.
|
|
60
61
|
if (isInvalidFileName(newFileInfo.filename)) {
|
|
@@ -67,10 +68,17 @@ export async function createNewFluidFile(
|
|
|
67
68
|
let sharingLink: string | undefined;
|
|
68
69
|
let sharingLinkErrorReason: string | undefined;
|
|
69
70
|
if (createNewSummary === undefined) {
|
|
70
|
-
itemId = await createNewEmptyFluidFile(
|
|
71
|
+
itemId = await createNewEmptyFluidFile(
|
|
72
|
+
getStorageToken, newFileInfo, logger, epochTracker, forceAccessTokenViaAuthorizationHeader);
|
|
71
73
|
} else {
|
|
72
74
|
const content = await createNewFluidFileFromSummary(
|
|
73
|
-
getStorageToken,
|
|
75
|
+
getStorageToken,
|
|
76
|
+
newFileInfo,
|
|
77
|
+
logger,
|
|
78
|
+
createNewSummary,
|
|
79
|
+
epochTracker,
|
|
80
|
+
forceAccessTokenViaAuthorizationHeader,
|
|
81
|
+
);
|
|
74
82
|
itemId = content.itemId;
|
|
75
83
|
summaryHandle = content.id;
|
|
76
84
|
sharingLink = content.sharingLink;
|
|
@@ -108,6 +116,7 @@ export async function createNewEmptyFluidFile(
|
|
|
108
116
|
newFileInfo: INewFileInfo,
|
|
109
117
|
logger: ITelemetryLogger,
|
|
110
118
|
epochTracker: EpochTracker,
|
|
119
|
+
forceAccessTokenViaAuthorizationHeader: boolean,
|
|
111
120
|
): Promise<string> {
|
|
112
121
|
const filePath = newFileInfo.filePath ? encodeURIComponent(`/${newFileInfo.filePath}`) : "";
|
|
113
122
|
// add .tmp extension to empty file (host is expected to rename)
|
|
@@ -123,7 +132,8 @@ export async function createNewEmptyFluidFile(
|
|
|
123
132
|
logger,
|
|
124
133
|
{ eventName: "createNewEmptyFile" },
|
|
125
134
|
async (event) => {
|
|
126
|
-
const { url, headers } = getUrlAndHeadersWithAuth(
|
|
135
|
+
const { url, headers } = getUrlAndHeadersWithAuth(
|
|
136
|
+
initialUrl, storageToken, forceAccessTokenViaAuthorizationHeader);
|
|
127
137
|
headers["Content-Type"] = "application/json";
|
|
128
138
|
|
|
129
139
|
const fetchResponse = await runWithRetry(
|
|
@@ -163,6 +173,7 @@ export async function createNewFluidFileFromSummary(
|
|
|
163
173
|
logger: ITelemetryLogger,
|
|
164
174
|
createNewSummary: ISummaryTree,
|
|
165
175
|
epochTracker: EpochTracker,
|
|
176
|
+
forceAccessTokenViaAuthorizationHeader: boolean,
|
|
166
177
|
): Promise<ICreateFileResponse> {
|
|
167
178
|
const filePath = newFileInfo.filePath ? encodeURIComponent(`/${newFileInfo.filePath}`) : "";
|
|
168
179
|
const encodedFilename = encodeURIComponent(newFileInfo.filename);
|
|
@@ -181,7 +192,8 @@ export async function createNewFluidFileFromSummary(
|
|
|
181
192
|
logger,
|
|
182
193
|
{ eventName: "createNewFile" },
|
|
183
194
|
async (event) => {
|
|
184
|
-
const { url, headers } = getUrlAndHeadersWithAuth(
|
|
195
|
+
const { url, headers } = getUrlAndHeadersWithAuth(
|
|
196
|
+
initialUrl, storageToken, forceAccessTokenViaAuthorizationHeader);
|
|
185
197
|
headers["Content-Type"] = "application/json";
|
|
186
198
|
|
|
187
199
|
const fetchResponse = await runWithRetry(
|
package/src/epochTracker.ts
CHANGED
|
@@ -18,13 +18,14 @@ import {
|
|
|
18
18
|
} from "@fluidframework/odsp-driver-definitions";
|
|
19
19
|
import { DriverErrorType } from "@fluidframework/driver-definitions";
|
|
20
20
|
import { PerformanceEvent, isFluidError, normalizeError } from "@fluidframework/telemetry-utils";
|
|
21
|
-
import { fetchAndParseAsJSONHelper, fetchArray, IOdspResponse } from "./odspUtils";
|
|
21
|
+
import { fetchAndParseAsJSONHelper, fetchArray, getOdspResolvedUrl, IOdspResponse } from "./odspUtils";
|
|
22
22
|
import {
|
|
23
23
|
IOdspCache,
|
|
24
24
|
INonPersistentCache,
|
|
25
25
|
IPersistedFileCache,
|
|
26
26
|
} from "./odspCache";
|
|
27
27
|
import { IVersionedValueWithEpoch, persistedCacheValueVersion } from "./contracts";
|
|
28
|
+
import { ClpCompliantAppHeader } from "./contractsPublic";
|
|
28
29
|
|
|
29
30
|
export type FetchType = "blob" | "createBlob" | "createFile" | "joinSession" | "ops" | "test" | "snapshotTree" |
|
|
30
31
|
"treesLatest" | "uploadSummary" | "push" | "versions";
|
|
@@ -170,8 +171,9 @@ export class EpochTracker implements IPersistedFileCache {
|
|
|
170
171
|
fetchOptions: RequestInit,
|
|
171
172
|
fetchType: FetchType,
|
|
172
173
|
addInBody: boolean = false,
|
|
174
|
+
fetchReason?: string,
|
|
173
175
|
): Promise<IOdspResponse<T>> {
|
|
174
|
-
const clientCorrelationId = this.formatClientCorrelationId();
|
|
176
|
+
const clientCorrelationId = this.formatClientCorrelationId(fetchReason);
|
|
175
177
|
// Add epoch in fetch request.
|
|
176
178
|
this.addEpochInRequest(fetchOptions, addInBody, clientCorrelationId);
|
|
177
179
|
let epochFromResponse: string | undefined;
|
|
@@ -211,8 +213,9 @@ export class EpochTracker implements IPersistedFileCache {
|
|
|
211
213
|
fetchOptions: {[index: string]: any},
|
|
212
214
|
fetchType: FetchType,
|
|
213
215
|
addInBody: boolean = false,
|
|
216
|
+
fetchReason?: string,
|
|
214
217
|
) {
|
|
215
|
-
const clientCorrelationId = this.formatClientCorrelationId();
|
|
218
|
+
const clientCorrelationId = this.formatClientCorrelationId(fetchReason);
|
|
216
219
|
// Add epoch in fetch request.
|
|
217
220
|
this.addEpochInRequest(fetchOptions, addInBody, clientCorrelationId);
|
|
218
221
|
let epochFromResponse: string | undefined;
|
|
@@ -245,12 +248,16 @@ export class EpochTracker implements IPersistedFileCache {
|
|
|
245
248
|
addInBody: boolean,
|
|
246
249
|
clientCorrelationId: string,
|
|
247
250
|
) {
|
|
251
|
+
const isClpCompliantApp = getOdspResolvedUrl(this.fileEntry.resolvedUrl).isClpCompliantApp;
|
|
248
252
|
if (addInBody) {
|
|
249
253
|
const headers: {[key: string]: string} = {};
|
|
250
254
|
headers["X-RequestStats"] = clientCorrelationId;
|
|
251
255
|
if (this.fluidEpoch !== undefined) {
|
|
252
256
|
headers["x-fluid-epoch"] = this.fluidEpoch;
|
|
253
257
|
}
|
|
258
|
+
if (isClpCompliantApp) {
|
|
259
|
+
headers[ClpCompliantAppHeader.isClpCompliantApp] = isClpCompliantApp.toString();
|
|
260
|
+
}
|
|
254
261
|
this.addParamInBody(fetchOptions, headers);
|
|
255
262
|
} else {
|
|
256
263
|
const addHeader = (key: string, val: string) => {
|
|
@@ -264,6 +271,9 @@ export class EpochTracker implements IPersistedFileCache {
|
|
|
264
271
|
if (this.fluidEpoch !== undefined) {
|
|
265
272
|
addHeader("x-fluid-epoch", this.fluidEpoch);
|
|
266
273
|
}
|
|
274
|
+
if (isClpCompliantApp) {
|
|
275
|
+
addHeader(ClpCompliantAppHeader.isClpCompliantApp, isClpCompliantApp.toString());
|
|
276
|
+
}
|
|
267
277
|
}
|
|
268
278
|
}
|
|
269
279
|
|
|
@@ -285,8 +295,12 @@ export class EpochTracker implements IPersistedFileCache {
|
|
|
285
295
|
fetchOptions.body = formParams.join("\r\n");
|
|
286
296
|
}
|
|
287
297
|
|
|
288
|
-
private formatClientCorrelationId() {
|
|
289
|
-
|
|
298
|
+
private formatClientCorrelationId(fetchReason?: string) {
|
|
299
|
+
const items: string[] = [`driverId=${this.driverId}`, `RequestNumber=${this.networkCallNumber++}`];
|
|
300
|
+
if (fetchReason !== undefined) {
|
|
301
|
+
items.push(`fetchReason=${fetchReason}`);
|
|
302
|
+
}
|
|
303
|
+
return items.join(", ");
|
|
290
304
|
}
|
|
291
305
|
|
|
292
306
|
protected validateEpochFromResponse(
|
|
@@ -395,13 +409,14 @@ export class EpochTrackerWithRedemption extends EpochTracker {
|
|
|
395
409
|
fetchOptions: {[index: string]: any},
|
|
396
410
|
fetchType: FetchType,
|
|
397
411
|
addInBody: boolean = false,
|
|
412
|
+
fetchReason?: string,
|
|
398
413
|
): Promise<IOdspResponse<T>> {
|
|
399
414
|
// Optimize the flow if we know that treesLatestDeferral was already completed by the timer we started
|
|
400
415
|
// joinSession call. If we did - there is no reason to repeat the call as it will fail with same error.
|
|
401
416
|
const completed = this.treesLatestDeferral.isCompleted;
|
|
402
417
|
|
|
403
418
|
try {
|
|
404
|
-
return await super.fetchAndParseAsJSON<T>(url, fetchOptions, fetchType, addInBody);
|
|
419
|
+
return await super.fetchAndParseAsJSON<T>(url, fetchOptions, fetchType, addInBody, fetchReason);
|
|
405
420
|
} catch (error) {
|
|
406
421
|
// Only handling here treesLatest. If createFile failed, we should never try to do joinSession.
|
|
407
422
|
// Similar, if getVersions failed, we should not do any further storage calls.
|
package/src/fetchSnapshot.ts
CHANGED
|
@@ -39,6 +39,7 @@ import { EpochTracker } from "./epochTracker";
|
|
|
39
39
|
* @param storageFetchWrapper - Implementation of the get/post methods used to fetch the snapshot
|
|
40
40
|
* @param versionId - id of specific snapshot to be fetched
|
|
41
41
|
* @param fetchFullSnapshot - whether we want to fetch full snapshot(with blobs)
|
|
42
|
+
* @param forceAccessTokenViaAuthorizationHeader - whether to force passing given token via authorization header
|
|
42
43
|
* @returns A promise of the snapshot and the status code of the response
|
|
43
44
|
*/
|
|
44
45
|
export async function fetchSnapshot(
|
|
@@ -46,6 +47,7 @@ export async function fetchSnapshot(
|
|
|
46
47
|
token: string | null,
|
|
47
48
|
versionId: string,
|
|
48
49
|
fetchFullSnapshot: boolean,
|
|
50
|
+
forceAccessTokenViaAuthorizationHeader: boolean,
|
|
49
51
|
logger: ITelemetryLogger,
|
|
50
52
|
snapshotDownloader: (url: string, fetchOptions: {[index: string]: any}) => Promise<IOdspResponse<unknown>>,
|
|
51
53
|
): Promise<ISnapshotContents> {
|
|
@@ -61,7 +63,8 @@ export async function fetchSnapshot(
|
|
|
61
63
|
}
|
|
62
64
|
|
|
63
65
|
const queryString = getQueryString(queryParams);
|
|
64
|
-
const { url, headers } = getUrlAndHeadersWithAuth(
|
|
66
|
+
const { url, headers } = getUrlAndHeadersWithAuth(
|
|
67
|
+
`${snapshotUrl}${path}${queryString}`, token, forceAccessTokenViaAuthorizationHeader);
|
|
65
68
|
const response = await PerformanceEvent.timedExecAsync(
|
|
66
69
|
logger,
|
|
67
70
|
{
|
|
@@ -77,6 +80,7 @@ export async function fetchSnapshotWithRedeem(
|
|
|
77
80
|
odspResolvedUrl: IOdspResolvedUrl,
|
|
78
81
|
storageTokenFetcher: InstrumentedStorageTokenFetcher,
|
|
79
82
|
snapshotOptions: ISnapshotOptions | undefined,
|
|
83
|
+
forceAccessTokenViaAuthorizationHeader: boolean,
|
|
80
84
|
logger: ITelemetryLogger,
|
|
81
85
|
snapshotDownloader: (
|
|
82
86
|
finalOdspResolvedUrl: IOdspResolvedUrl,
|
|
@@ -88,6 +92,12 @@ export async function fetchSnapshotWithRedeem(
|
|
|
88
92
|
removeEntries: () => Promise<void>,
|
|
89
93
|
enableRedeemFallback?: boolean,
|
|
90
94
|
): Promise<ISnapshotContents> {
|
|
95
|
+
// back-compat: This block to be removed with #8784 when we only consume/consider odsp resolvers that are >= 0.51
|
|
96
|
+
const sharingLinkToRedeem = (odspResolvedUrl as any).sharingLinkToRedeem;
|
|
97
|
+
if(sharingLinkToRedeem) {
|
|
98
|
+
odspResolvedUrl.shareLinkInfo = {...odspResolvedUrl.shareLinkInfo, sharingLinkToRedeem}
|
|
99
|
+
}
|
|
100
|
+
|
|
91
101
|
return fetchLatestSnapshotCore(
|
|
92
102
|
odspResolvedUrl,
|
|
93
103
|
storageTokenFetcher,
|
|
@@ -103,16 +113,15 @@ export async function fetchSnapshotWithRedeem(
|
|
|
103
113
|
eventName: "RedeemFallback",
|
|
104
114
|
errorType: error.errorType,
|
|
105
115
|
}, error);
|
|
106
|
-
await redeemSharingLink(
|
|
116
|
+
await redeemSharingLink(
|
|
117
|
+
odspResolvedUrl, storageTokenFetcher, logger, forceAccessTokenViaAuthorizationHeader);
|
|
107
118
|
const odspResolvedUrlWithoutShareLink: IOdspResolvedUrl =
|
|
108
|
-
{ ...odspResolvedUrl,
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
sharingLinkToRedeem: undefined,
|
|
119
|
+
{ ...odspResolvedUrl,
|
|
120
|
+
shareLinkInfo: {
|
|
121
|
+
...odspResolvedUrl.shareLinkInfo,
|
|
122
|
+
sharingLinkToRedeem: undefined
|
|
123
|
+
}
|
|
114
124
|
};
|
|
115
|
-
}
|
|
116
125
|
|
|
117
126
|
return fetchLatestSnapshotCore(
|
|
118
127
|
odspResolvedUrlWithoutShareLink,
|
|
@@ -141,6 +150,7 @@ async function redeemSharingLink(
|
|
|
141
150
|
odspResolvedUrl: IOdspResolvedUrl,
|
|
142
151
|
storageTokenFetcher: InstrumentedStorageTokenFetcher,
|
|
143
152
|
logger: ITelemetryLogger,
|
|
153
|
+
forceAccessTokenViaAuthorizationHeader: boolean,
|
|
144
154
|
) {
|
|
145
155
|
return PerformanceEvent.timedExecAsync(
|
|
146
156
|
logger,
|
|
@@ -148,12 +158,13 @@ async function redeemSharingLink(
|
|
|
148
158
|
eventName: "RedeemShareLink",
|
|
149
159
|
},
|
|
150
160
|
async () => getWithRetryForTokenRefresh(async (tokenFetchOptions) => {
|
|
151
|
-
assert(!!odspResolvedUrl.sharingLinkToRedeem,
|
|
161
|
+
assert(!!odspResolvedUrl.shareLinkInfo?.sharingLinkToRedeem,
|
|
152
162
|
0x1ed /* "Share link should be present" */);
|
|
153
163
|
const storageToken = await storageTokenFetcher(tokenFetchOptions, "RedeemShareLink");
|
|
154
|
-
const encodedShareUrl = getEncodedShareUrl(odspResolvedUrl.sharingLinkToRedeem);
|
|
164
|
+
const encodedShareUrl = getEncodedShareUrl(odspResolvedUrl.shareLinkInfo?.sharingLinkToRedeem);
|
|
155
165
|
const redeemUrl = `${odspResolvedUrl.siteUrl}/_api/v2.0/shares/${encodedShareUrl}`;
|
|
156
|
-
const { url, headers } = getUrlAndHeadersWithAuth(
|
|
166
|
+
const { url, headers } = getUrlAndHeadersWithAuth(
|
|
167
|
+
redeemUrl, storageToken, forceAccessTokenViaAuthorizationHeader);
|
|
157
168
|
headers.prefer = "redeemSharingLink";
|
|
158
169
|
return fetchAndParseAsJSONHelper(url, { headers });
|
|
159
170
|
}),
|
|
@@ -189,7 +200,7 @@ async function fetchLatestSnapshotCore(
|
|
|
189
200
|
const perfEvent = {
|
|
190
201
|
eventName: "TreesLatest",
|
|
191
202
|
attempts: tokenFetchOptions.refresh ? 2 : 1,
|
|
192
|
-
shareLinkPresent: odspResolvedUrl.sharingLinkToRedeem !== undefined,
|
|
203
|
+
shareLinkPresent: odspResolvedUrl.shareLinkInfo?.sharingLinkToRedeem !== undefined,
|
|
193
204
|
redeemFallbackEnabled: enableRedeemFallback,
|
|
194
205
|
};
|
|
195
206
|
if (snapshotOptions !== undefined) {
|
|
@@ -423,8 +434,8 @@ function getFormBodyAndHeaders(
|
|
|
423
434
|
}
|
|
424
435
|
});
|
|
425
436
|
}
|
|
426
|
-
if (odspResolvedUrl.sharingLinkToRedeem) {
|
|
427
|
-
formParams.push(`sl: ${odspResolvedUrl.sharingLinkToRedeem}`);
|
|
437
|
+
if (odspResolvedUrl.shareLinkInfo?.sharingLinkToRedeem) {
|
|
438
|
+
formParams.push(`sl: ${odspResolvedUrl.shareLinkInfo?.sharingLinkToRedeem}`);
|
|
428
439
|
}
|
|
429
440
|
formParams.push(`_post: 1`);
|
|
430
441
|
formParams.push(`\r\n--${formBoundary}--`);
|
|
@@ -467,6 +478,12 @@ export async function downloadSnapshot(
|
|
|
467
478
|
controller?: AbortController,
|
|
468
479
|
epochTracker?: EpochTracker,
|
|
469
480
|
): Promise<ISnapshotRequestAndResponseOptions> {
|
|
481
|
+
// back-compat: This block to be removed with #8784 when we only consume/consider odsp resolvers that are >= 0.51
|
|
482
|
+
const sharingLinkToRedeem = (odspResolvedUrl as any).sharingLinkToRedeem;
|
|
483
|
+
if(sharingLinkToRedeem) {
|
|
484
|
+
odspResolvedUrl.shareLinkInfo = {...odspResolvedUrl.shareLinkInfo, sharingLinkToRedeem}
|
|
485
|
+
}
|
|
486
|
+
|
|
470
487
|
if (fetchBinarySnapshotFormat) {
|
|
471
488
|
// Logging an event here as it is not supposed to be used in production yet and only in experimental mode.
|
|
472
489
|
logger.sendTelemetryEvent({ eventName: "BinarySnapshotFetched" });
|
|
@@ -477,7 +494,7 @@ export async function downloadSnapshot(
|
|
|
477
494
|
}
|
|
478
495
|
|
|
479
496
|
function isRedeemSharingLinkError(odspResolvedUrl: IOdspResolvedUrl, error: any) {
|
|
480
|
-
if (odspResolvedUrl.sharingLinkToRedeem !== undefined
|
|
497
|
+
if (odspResolvedUrl.shareLinkInfo?.sharingLinkToRedeem !== undefined
|
|
481
498
|
&& (typeof error === "object" && error !== null)
|
|
482
499
|
&& (error.errorType === DriverErrorType.authorizationError
|
|
483
500
|
|| error.errorType === DriverErrorType.fileNotFoundOrAccessDeniedError)) {
|
package/src/getFileLink.ts
CHANGED
|
@@ -84,7 +84,7 @@ async function getFileLinkCore(
|
|
|
84
84
|
identityType: IdentityType,
|
|
85
85
|
logger: ITelemetryLogger,
|
|
86
86
|
): Promise<string> {
|
|
87
|
-
const fileItem = await getFileItemLite(getToken, odspUrlParts, logger);
|
|
87
|
+
const fileItem = await getFileItemLite(getToken, odspUrlParts, logger, identityType === "Consumer");
|
|
88
88
|
|
|
89
89
|
// ODC canonical link does not require any additional processing
|
|
90
90
|
if (identityType === "Consumer") {
|
|
@@ -104,7 +104,10 @@ async function getFileLinkCore(
|
|
|
104
104
|
const { url, headers } = getUrlAndHeadersWithAuth(
|
|
105
105
|
`${odspUrlParts.siteUrl}/_api/web/GetFileByUrl(@a1)/ListItemAllFields/GetSharingInformation?@a1=${
|
|
106
106
|
encodeURIComponent(`'${fileItem.webDavUrl}'`)
|
|
107
|
-
}`,
|
|
107
|
+
}`,
|
|
108
|
+
tokenFromResponse(token),
|
|
109
|
+
false,
|
|
110
|
+
);
|
|
108
111
|
const requestInit = {
|
|
109
112
|
method: "POST",
|
|
110
113
|
headers: {
|
|
@@ -152,6 +155,7 @@ async function getFileItemLite(
|
|
|
152
155
|
getToken: TokenFetcher<OdspResourceTokenFetchOptions>,
|
|
153
156
|
odspUrlParts: IOdspUrlParts,
|
|
154
157
|
logger: ITelemetryLogger,
|
|
158
|
+
forceAccessTokenViaAuthorizationHeader: boolean,
|
|
155
159
|
): Promise<FileItemLite> {
|
|
156
160
|
return PerformanceEvent.timedExecAsync(
|
|
157
161
|
logger,
|
|
@@ -166,6 +170,7 @@ async function getFileItemLite(
|
|
|
166
170
|
const { url, headers } = getUrlAndHeadersWithAuth(
|
|
167
171
|
`${siteUrl}/_api/v2.0/drives/${driveId}/items/${itemId}?select=webUrl,webDavUrl`,
|
|
168
172
|
tokenFromResponse(token),
|
|
173
|
+
forceAccessTokenViaAuthorizationHeader,
|
|
169
174
|
);
|
|
170
175
|
const requestInit = { method: "GET", headers };
|
|
171
176
|
const response = await fetchHelper(url, requestInit);
|
|
@@ -3,48 +3,34 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const queryParamStart = url.indexOf("?");
|
|
12
|
-
|
|
13
|
-
if (queryParamStart === -1) {
|
|
14
|
-
return 0;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
return url.length - queryParamStart - 1;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
// eslint-disable-next-line max-len
|
|
21
|
-
export function getUrlAndHeadersWithAuth(url: string, token: string | null): { url: string, headers: { [index: string]: string } } {
|
|
6
|
+
export function getUrlAndHeadersWithAuth(
|
|
7
|
+
url: string,
|
|
8
|
+
token: string | null,
|
|
9
|
+
forceAccessTokenViaAuthorizationHeader: boolean,
|
|
10
|
+
): { url: string, headers: { [index: string]: string } } {
|
|
22
11
|
if (!token || token.length === 0) {
|
|
23
12
|
return { url, headers: {} };
|
|
24
13
|
}
|
|
25
14
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
//
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
headers: {},
|
|
46
|
-
url: url + tokenQueryParam,
|
|
47
|
-
};
|
|
15
|
+
if (!forceAccessTokenViaAuthorizationHeader) {
|
|
16
|
+
// Pass access token via query string: this will make request be treated as 'simple' request
|
|
17
|
+
// which does not require OPTIONS call as part of CORS check.
|
|
18
|
+
const urlWithAccessTokenInQueryString = new URL(url);
|
|
19
|
+
// IMPORTANT: Do not apply encodeURIComponent to token, param value is automatically encoded
|
|
20
|
+
// when set via URLSearchParams class
|
|
21
|
+
urlWithAccessTokenInQueryString.searchParams.set("access_token", token);
|
|
22
|
+
// ODSP APIs have a limitation that the query string cannot exceed 2048 characters.
|
|
23
|
+
// If the query string exceeds 2048, we have to fall back to sending the access token as a header, which
|
|
24
|
+
// has a negative performance implication as it adds a performance overhead.
|
|
25
|
+
// NOTE: URL.search.length value includes '?' symbol and it is unclear whether backend logic which enforces
|
|
26
|
+
// query length limit accounts for it. This logic errs on side of caution and includes that key in overall
|
|
27
|
+
// query length.
|
|
28
|
+
if (urlWithAccessTokenInQueryString.search.length <= 2048) {
|
|
29
|
+
return {
|
|
30
|
+
headers: {},
|
|
31
|
+
url: urlWithAccessTokenInQueryString.href,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
48
34
|
}
|
|
49
35
|
|
|
50
36
|
return {
|
|
@@ -53,9 +53,6 @@ export class OdspDeltaStorageService {
|
|
|
53
53
|
let postBody = `--${formBoundary}\r\n`;
|
|
54
54
|
postBody += `Authorization: Bearer ${storageToken}\r\n`;
|
|
55
55
|
postBody += `X-HTTP-Method-Override: GET\r\n`;
|
|
56
|
-
if (fetchReason !== undefined) {
|
|
57
|
-
postBody += `fetchReason: ${fetchReason}\r\n`;
|
|
58
|
-
}
|
|
59
56
|
|
|
60
57
|
postBody += `_post: 1\r\n`;
|
|
61
58
|
postBody += `\r\n--${formBoundary}--`;
|
|
@@ -81,6 +78,7 @@ export class OdspDeltaStorageService {
|
|
|
81
78
|
},
|
|
82
79
|
"ops",
|
|
83
80
|
true,
|
|
81
|
+
fetchReason,
|
|
84
82
|
);
|
|
85
83
|
clearTimeout(timer);
|
|
86
84
|
const deltaStorageResponse = response.content;
|
|
@@ -104,6 +104,7 @@ export class OdspDocumentServiceFactoryCore implements IDocumentServiceFactory {
|
|
|
104
104
|
cacheAndTracker.epochTracker,
|
|
105
105
|
fileEntry,
|
|
106
106
|
this.hostPolicy.cacheCreateNewSummary ?? true,
|
|
107
|
+
!!this.hostPolicy.sessionOptions?.forceAccessTokenViaAuthorizationHeader,
|
|
107
108
|
);
|
|
108
109
|
const docService = this.createDocumentServiceCore(odspResolvedUrl, odspLogger, cacheAndTracker);
|
|
109
110
|
event.end({
|
|
@@ -40,7 +40,7 @@ import {
|
|
|
40
40
|
getWithRetryForTokenRefresh,
|
|
41
41
|
ISnapshotContents,
|
|
42
42
|
} from "./odspUtils";
|
|
43
|
-
import { EpochTracker } from "./epochTracker";
|
|
43
|
+
import { defaultCacheExpiryTimeoutMs, EpochTracker } from "./epochTracker";
|
|
44
44
|
import { OdspSummaryUploadManager } from "./odspSummaryUploadManager";
|
|
45
45
|
import { FlushResult } from "./odspDocumentDeltaConnection";
|
|
46
46
|
|
|
@@ -167,6 +167,7 @@ export class OdspDocumentStorageService implements IDocumentStorageService {
|
|
|
167
167
|
// Note that duplication of content should not have significant impact for bytes over wire as
|
|
168
168
|
// compression of http payload mostly takes care of it, but it does impact storage size and in-memory sizes.
|
|
169
169
|
minBlobSize: 2048,
|
|
170
|
+
maximumCacheDurationMs: defaultCacheExpiryTimeoutMs,
|
|
170
171
|
};
|
|
171
172
|
|
|
172
173
|
private readonly commitCache: Map<string, api.ISnapshotTree> = new Map();
|
|
@@ -224,7 +225,13 @@ export class OdspDocumentStorageService implements IDocumentStorageService {
|
|
|
224
225
|
this.snapshotUrl = this.odspResolvedUrl.endpoints.snapshotStorageUrl;
|
|
225
226
|
this.attachmentPOSTUrl = this.odspResolvedUrl.endpoints.attachmentPOSTStorageUrl;
|
|
226
227
|
this.attachmentGETUrl = this.odspResolvedUrl.endpoints.attachmentGETStorageUrl;
|
|
227
|
-
this.odspSummaryUploadManager = new OdspSummaryUploadManager(
|
|
228
|
+
this.odspSummaryUploadManager = new OdspSummaryUploadManager(
|
|
229
|
+
this.snapshotUrl,
|
|
230
|
+
getStorageToken,
|
|
231
|
+
logger,
|
|
232
|
+
epochTracker,
|
|
233
|
+
!!this.hostPolicy.sessionOptions?.forceAccessTokenViaAuthorizationHeader,
|
|
234
|
+
);
|
|
228
235
|
}
|
|
229
236
|
|
|
230
237
|
public get repositoryUrl(): string {
|
|
@@ -236,7 +243,11 @@ export class OdspDocumentStorageService implements IDocumentStorageService {
|
|
|
236
243
|
|
|
237
244
|
const response = await getWithRetryForTokenRefresh(async (options) => {
|
|
238
245
|
const storageToken = await this.getStorageToken(options, "CreateBlob");
|
|
239
|
-
const { url, headers } = getUrlAndHeadersWithAuth(
|
|
246
|
+
const { url, headers } = getUrlAndHeadersWithAuth(
|
|
247
|
+
`${this.attachmentPOSTUrl}/content`,
|
|
248
|
+
storageToken,
|
|
249
|
+
!!this.hostPolicy.sessionOptions?.forceAccessTokenViaAuthorizationHeader,
|
|
250
|
+
);
|
|
240
251
|
headers["Content-Type"] = "application/octet-stream";
|
|
241
252
|
|
|
242
253
|
return PerformanceEvent.timedExecAsync(
|
|
@@ -279,7 +290,11 @@ export class OdspDocumentStorageService implements IDocumentStorageService {
|
|
|
279
290
|
blob = await getWithRetryForTokenRefresh(async (options) => {
|
|
280
291
|
const storageToken = await this.getStorageToken(options, "GetBlob");
|
|
281
292
|
const unAuthedUrl = `${this.attachmentGETUrl}/${encodeURIComponent(blobId)}/content`;
|
|
282
|
-
const { url, headers } = getUrlAndHeadersWithAuth(
|
|
293
|
+
const { url, headers } = getUrlAndHeadersWithAuth(
|
|
294
|
+
unAuthedUrl,
|
|
295
|
+
storageToken,
|
|
296
|
+
!!this.hostPolicy.sessionOptions?.forceAccessTokenViaAuthorizationHeader,
|
|
297
|
+
);
|
|
283
298
|
|
|
284
299
|
return PerformanceEvent.timedExecAsync(
|
|
285
300
|
this.logger,
|
|
@@ -495,7 +510,11 @@ export class OdspDocumentStorageService implements IDocumentStorageService {
|
|
|
495
510
|
|
|
496
511
|
return getWithRetryForTokenRefresh(async (options) => {
|
|
497
512
|
const storageToken = await this.getStorageToken(options, "GetVersions");
|
|
498
|
-
const { url, headers } = getUrlAndHeadersWithAuth(
|
|
513
|
+
const { url, headers } = getUrlAndHeadersWithAuth(
|
|
514
|
+
`${this.snapshotUrl}/versions?count=${count}`,
|
|
515
|
+
storageToken,
|
|
516
|
+
!!this.hostPolicy.sessionOptions?.forceAccessTokenViaAuthorizationHeader,
|
|
517
|
+
);
|
|
499
518
|
|
|
500
519
|
// Fetch the latest snapshot versions for the document
|
|
501
520
|
const response = await PerformanceEvent.timedExecAsync(
|
|
@@ -594,11 +613,13 @@ export class OdspDocumentStorageService implements IDocumentStorageService {
|
|
|
594
613
|
this.odspResolvedUrl,
|
|
595
614
|
this.getStorageToken,
|
|
596
615
|
snapshotOptions,
|
|
616
|
+
!!this.hostPolicy.sessionOptions?.forceAccessTokenViaAuthorizationHeader,
|
|
597
617
|
this.logger,
|
|
598
618
|
snapshotDownloader,
|
|
599
619
|
putInCache,
|
|
600
620
|
removeEntries,
|
|
601
|
-
this.hostPolicy.enableRedeemFallback
|
|
621
|
+
this.hostPolicy.enableRedeemFallback,
|
|
622
|
+
);
|
|
602
623
|
return odspSnapshot;
|
|
603
624
|
} catch (error) {
|
|
604
625
|
const errorType = error.errorType;
|
|
@@ -617,11 +638,13 @@ export class OdspDocumentStorageService implements IDocumentStorageService {
|
|
|
617
638
|
this.odspResolvedUrl,
|
|
618
639
|
this.getStorageToken,
|
|
619
640
|
snapshotOptionsWithoutBlobs,
|
|
641
|
+
!!this.hostPolicy.sessionOptions?.forceAccessTokenViaAuthorizationHeader,
|
|
620
642
|
this.logger,
|
|
621
643
|
snapshotDownloader,
|
|
622
644
|
putInCache,
|
|
623
645
|
removeEntries,
|
|
624
|
-
this.hostPolicy.enableRedeemFallback
|
|
646
|
+
this.hostPolicy.enableRedeemFallback,
|
|
647
|
+
);
|
|
625
648
|
return odspSnapshot;
|
|
626
649
|
}
|
|
627
650
|
throw error;
|
|
@@ -729,7 +752,15 @@ export class OdspDocumentStorageService implements IDocumentStorageService {
|
|
|
729
752
|
"snapshotTree",
|
|
730
753
|
);
|
|
731
754
|
};
|
|
732
|
-
const snapshot = await fetchSnapshot(
|
|
755
|
+
const snapshot = await fetchSnapshot(
|
|
756
|
+
this.snapshotUrl!,
|
|
757
|
+
storageToken,
|
|
758
|
+
id,
|
|
759
|
+
this.fetchFullSnapshot,
|
|
760
|
+
!!this.hostPolicy.sessionOptions?.forceAccessTokenViaAuthorizationHeader,
|
|
761
|
+
this.logger,
|
|
762
|
+
snapshotDownloader,
|
|
763
|
+
);
|
|
733
764
|
let treeId = "";
|
|
734
765
|
if (snapshot.snapshotTree) {
|
|
735
766
|
assert(snapshot.snapshotTree.id !== undefined, 0x222 /* "Root tree should contain the id!!" */);
|
|
@@ -11,6 +11,7 @@ import { createOdspUrl } from "./createOdspUrl";
|
|
|
11
11
|
import { getApiRoot } from "./odspUrlHelper";
|
|
12
12
|
import { getOdspResolvedUrl } from "./odspUtils";
|
|
13
13
|
import { getHashedDocumentId } from "./odspPublicUtils";
|
|
14
|
+
import { ClpCompliantAppHeader } from "./contractsPublic";
|
|
14
15
|
|
|
15
16
|
function getUrlBase(siteUrl: string, driveId: string, itemId: string, fileVersion?: string) {
|
|
16
17
|
const siteOrigin = new URL(siteUrl).origin;
|
|
@@ -101,6 +102,7 @@ export class OdspDriverUrlResolver implements IUrlResolver {
|
|
|
101
102
|
},
|
|
102
103
|
fileVersion: undefined,
|
|
103
104
|
shareLinkInfo,
|
|
105
|
+
isClpCompliantApp: request.headers?.[ClpCompliantAppHeader.isClpCompliantApp],
|
|
104
106
|
};
|
|
105
107
|
}
|
|
106
108
|
const { siteUrl, driveId, itemId, path, containerPackageName, fileVersion } = decodeOdspUrl(request.url);
|
|
@@ -142,6 +144,7 @@ export class OdspDriverUrlResolver implements IUrlResolver {
|
|
|
142
144
|
containerPackageName,
|
|
143
145
|
},
|
|
144
146
|
fileVersion,
|
|
147
|
+
isClpCompliantApp: request.headers?.[ClpCompliantAppHeader.isClpCompliantApp],
|
|
145
148
|
};
|
|
146
149
|
}
|
|
147
150
|
|
|
@@ -133,9 +133,8 @@ export class OdspDriverUrlResolverForShareLink implements IUrlResolver {
|
|
|
133
133
|
// We need to remove the nav param if set by host when setting the sharelink as otherwise the shareLinkId
|
|
134
134
|
// when redeeming the share link during the redeem fallback for trees latest call becomes greater than
|
|
135
135
|
// the eligible length.
|
|
136
|
-
odspResolvedUrl.sharingLinkToRedeem = this.removeNavParam(request.url);
|
|
137
136
|
odspResolvedUrl.shareLinkInfo = Object.assign(odspResolvedUrl.shareLinkInfo || {},
|
|
138
|
-
{sharingLinkToRedeem:
|
|
137
|
+
{sharingLinkToRedeem: this.removeNavParam(request.url)});
|
|
139
138
|
}
|
|
140
139
|
if (odspResolvedUrl.itemId) {
|
|
141
140
|
// Kick start the sharing link request if we don't have it already as a performance optimization.
|
|
@@ -38,6 +38,7 @@ export class OdspSummaryUploadManager {
|
|
|
38
38
|
private readonly getStorageToken: InstrumentedStorageTokenFetcher,
|
|
39
39
|
logger: ITelemetryLogger,
|
|
40
40
|
private readonly epochTracker: EpochTracker,
|
|
41
|
+
private readonly forceAccessTokenViaAuthorizationHeader: boolean,
|
|
41
42
|
) {
|
|
42
43
|
this.mc = loggerToMonitoringContext(logger);
|
|
43
44
|
}
|
|
@@ -84,7 +85,11 @@ export class OdspSummaryUploadManager {
|
|
|
84
85
|
return getWithRetryForTokenRefresh(async (options) => {
|
|
85
86
|
const storageToken = await this.getStorageToken(options, "WriteSummaryTree");
|
|
86
87
|
|
|
87
|
-
const { url, headers } = getUrlAndHeadersWithAuth(
|
|
88
|
+
const { url, headers } = getUrlAndHeadersWithAuth(
|
|
89
|
+
`${this.snapshotUrl}/snapshot`,
|
|
90
|
+
storageToken,
|
|
91
|
+
this.forceAccessTokenViaAuthorizationHeader,
|
|
92
|
+
);
|
|
88
93
|
headers["Content-Type"] = "application/json";
|
|
89
94
|
if (parentHandle) {
|
|
90
95
|
headers["If-Match"] = `fluid:containerid=${parentHandle}`;
|
package/src/packageVersion.ts
CHANGED
|
@@ -31,6 +31,7 @@ import { IVersionedValueWithEpoch } from "./contracts";
|
|
|
31
31
|
* @param getStorageToken - function that can provide the storage token for a given site. This is
|
|
32
32
|
* is also referred to as the "VROOM" token in SPO.
|
|
33
33
|
* @param persistedCache - Cache to store the fetched snapshot.
|
|
34
|
+
* @param forceAccessTokenViaAuthorizationHeader - whether to force passing given token via authorization header.
|
|
34
35
|
* @param logger - Logger to have telemetry events.
|
|
35
36
|
* @param hostSnapshotFetchOptions - Options to fetch the snapshot if any. Otherwise default will be used.
|
|
36
37
|
* @param enableRedeemFallback - True to have the sharing link redeem fallback in case the Trees Latest/Redeem
|
|
@@ -42,6 +43,7 @@ export async function prefetchLatestSnapshot(
|
|
|
42
43
|
resolvedUrl: IResolvedUrl,
|
|
43
44
|
getStorageToken: TokenFetcher<OdspResourceTokenFetchOptions>,
|
|
44
45
|
persistedCache: IPersistedCache,
|
|
46
|
+
forceAccessTokenViaAuthorizationHeader: boolean,
|
|
45
47
|
logger: ITelemetryBaseLogger,
|
|
46
48
|
hostSnapshotFetchOptions: ISnapshotOptions | undefined,
|
|
47
49
|
enableRedeemFallback?: boolean,
|
|
@@ -84,6 +86,7 @@ export async function prefetchLatestSnapshot(
|
|
|
84
86
|
odspResolvedUrl,
|
|
85
87
|
storageTokenFetcher,
|
|
86
88
|
hostSnapshotFetchOptions,
|
|
89
|
+
forceAccessTokenViaAuthorizationHeader,
|
|
87
90
|
odspLogger,
|
|
88
91
|
snapshotDownloader,
|
|
89
92
|
putInCache,
|
|
@@ -54,7 +54,7 @@ export class RetryErrorsStorageAdapter implements IDocumentStorageService, IDisp
|
|
|
54
54
|
);
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
public async getVersions(versionId: string, count: number): Promise<IVersion[]> {
|
|
57
|
+
public async getVersions(versionId: string | null, count: number): Promise<IVersion[]> {
|
|
58
58
|
return this.runWithRetry(
|
|
59
59
|
async () => this.internalStorageService.getVersions(versionId, count),
|
|
60
60
|
"storage_getVersions",
|