@fluidframework/routerlicious-driver 2.0.0-dev.4.4.0.162253 → 2.0.0-dev.4.4.0.162574
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/documentService.d.ts +5 -2
- package/dist/documentService.d.ts.map +1 -1
- package/dist/documentService.js +11 -6
- package/dist/documentService.js.map +1 -1
- package/dist/documentServiceFactory.d.ts.map +1 -1
- package/dist/documentServiceFactory.js +9 -3
- package/dist/documentServiceFactory.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/restWrapper.d.ts +7 -4
- package/dist/restWrapper.d.ts.map +1 -1
- package/dist/restWrapper.js +41 -30
- package/dist/restWrapper.js.map +1 -1
- package/lib/documentService.d.ts +5 -2
- package/lib/documentService.d.ts.map +1 -1
- package/lib/documentService.js +12 -7
- package/lib/documentService.js.map +1 -1
- package/lib/documentServiceFactory.d.ts.map +1 -1
- package/lib/documentServiceFactory.js +10 -4
- package/lib/documentServiceFactory.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/restWrapper.d.ts +7 -4
- package/lib/restWrapper.d.ts.map +1 -1
- package/lib/restWrapper.js +38 -29
- package/lib/restWrapper.js.map +1 -1
- package/package.json +6 -6
- package/src/documentService.ts +24 -18
- package/src/documentServiceFactory.ts +43 -6
- package/src/packageVersion.ts +1 -1
- package/src/restWrapper.ts +71 -48
package/lib/restWrapper.js
CHANGED
|
@@ -65,12 +65,13 @@ export function getPropsToLogFromResponse(headers) {
|
|
|
65
65
|
return additionalProps;
|
|
66
66
|
}
|
|
67
67
|
export class RouterliciousRestWrapper extends RestWrapper {
|
|
68
|
-
constructor(logger, rateLimiter, fetchRefreshedToken, getAuthorizationHeader, useRestLess, baseurl, defaultQueryString = {}) {
|
|
68
|
+
constructor(logger, rateLimiter, fetchRefreshedToken, getAuthorizationHeader, useRestLess, baseurl, tokenP, defaultQueryString = {}) {
|
|
69
69
|
super(baseurl, defaultQueryString);
|
|
70
70
|
this.rateLimiter = rateLimiter;
|
|
71
71
|
this.fetchRefreshedToken = fetchRefreshedToken;
|
|
72
72
|
this.getAuthorizationHeader = getAuthorizationHeader;
|
|
73
73
|
this.useRestLess = useRestLess;
|
|
74
|
+
this.tokenP = tokenP;
|
|
74
75
|
this.restLess = new RestLessClient();
|
|
75
76
|
}
|
|
76
77
|
async request(requestConfig, statusCode, canRetry = true) {
|
|
@@ -145,11 +146,13 @@ export class RouterliciousRestWrapper extends RestWrapper {
|
|
|
145
146
|
"Authorization": this.getAuthorizationHeader(token) });
|
|
146
147
|
}
|
|
147
148
|
async getToken() {
|
|
149
|
+
var _a;
|
|
148
150
|
if (this.token !== undefined) {
|
|
149
151
|
return this.token;
|
|
150
152
|
}
|
|
151
|
-
const token = await this.fetchRefreshedToken();
|
|
153
|
+
const token = await ((_a = this.tokenP) !== null && _a !== void 0 ? _a : this.fetchRefreshedToken());
|
|
152
154
|
this.setToken(token);
|
|
155
|
+
this.tokenP = undefined;
|
|
153
156
|
return token;
|
|
154
157
|
}
|
|
155
158
|
setToken(token) {
|
|
@@ -157,23 +160,13 @@ export class RouterliciousRestWrapper extends RestWrapper {
|
|
|
157
160
|
}
|
|
158
161
|
}
|
|
159
162
|
export class RouterliciousStorageRestWrapper extends RouterliciousRestWrapper {
|
|
160
|
-
constructor(logger, rateLimiter, fetchToken, getAuthorizationHeader, useRestLess, baseurl, defaultQueryString = {}) {
|
|
161
|
-
super(logger, rateLimiter, fetchToken, getAuthorizationHeader, useRestLess, baseurl, defaultQueryString);
|
|
163
|
+
constructor(logger, rateLimiter, fetchToken, getAuthorizationHeader, useRestLess, baseurl, initialTokenP, defaultQueryString = {}) {
|
|
164
|
+
super(logger, rateLimiter, fetchToken, getAuthorizationHeader, useRestLess, baseurl, initialTokenP, defaultQueryString);
|
|
162
165
|
}
|
|
163
|
-
static async load(tenantId,
|
|
166
|
+
static async load(tenantId, tokenFetcher, logger, rateLimiter, useRestLess, baseurl, initialTokenP) {
|
|
164
167
|
const defaultQueryString = {
|
|
165
168
|
token: `${fromUtf8ToBase64(tenantId)}`,
|
|
166
169
|
};
|
|
167
|
-
const fetchStorageToken = async (refreshToken) => {
|
|
168
|
-
return PerformanceEvent.timedExecAsync(logger, {
|
|
169
|
-
eventName: "FetchStorageToken",
|
|
170
|
-
docId: documentId,
|
|
171
|
-
}, async () => {
|
|
172
|
-
// Craft credentials using tenant id and token
|
|
173
|
-
const storageToken = await tokenProvider.fetchStorageToken(tenantId, documentId, refreshToken);
|
|
174
|
-
return storageToken;
|
|
175
|
-
});
|
|
176
|
-
};
|
|
177
170
|
const getAuthorizationHeader = (token) => {
|
|
178
171
|
const credentials = {
|
|
179
172
|
password: token.jwt,
|
|
@@ -181,29 +174,45 @@ export class RouterliciousStorageRestWrapper extends RouterliciousRestWrapper {
|
|
|
181
174
|
};
|
|
182
175
|
return getAuthorizationTokenFromCredentials(credentials);
|
|
183
176
|
};
|
|
184
|
-
const restWrapper = new RouterliciousStorageRestWrapper(logger, rateLimiter,
|
|
177
|
+
const restWrapper = new RouterliciousStorageRestWrapper(logger, rateLimiter, tokenFetcher, getAuthorizationHeader, useRestLess, baseurl, initialTokenP, defaultQueryString);
|
|
185
178
|
return restWrapper;
|
|
186
179
|
}
|
|
187
180
|
}
|
|
188
181
|
export class RouterliciousOrdererRestWrapper extends RouterliciousRestWrapper {
|
|
189
|
-
constructor(logger, rateLimiter, fetchToken, getAuthorizationHeader, useRestLess, baseurl, defaultQueryString = {}) {
|
|
190
|
-
super(logger, rateLimiter, fetchToken, getAuthorizationHeader, useRestLess, baseurl, defaultQueryString);
|
|
182
|
+
constructor(logger, rateLimiter, fetchToken, getAuthorizationHeader, useRestLess, baseurl, initialTokenP, defaultQueryString = {}) {
|
|
183
|
+
super(logger, rateLimiter, fetchToken, getAuthorizationHeader, useRestLess, baseurl, initialTokenP, defaultQueryString);
|
|
191
184
|
}
|
|
192
|
-
static async load(
|
|
185
|
+
static async load(tokenFetcher, logger, rateLimiter, useRestLess, baseurl, initialTokenP) {
|
|
193
186
|
const getAuthorizationHeader = (token) => {
|
|
194
187
|
return `Basic ${token.jwt}`;
|
|
195
188
|
};
|
|
196
|
-
const
|
|
197
|
-
return PerformanceEvent.timedExecAsync(logger, {
|
|
198
|
-
eventName: "FetchOrdererToken",
|
|
199
|
-
docId: documentId,
|
|
200
|
-
}, async () => {
|
|
201
|
-
const ordererToken = await tokenProvider.fetchOrdererToken(tenantId, documentId, refreshToken);
|
|
202
|
-
return ordererToken;
|
|
203
|
-
});
|
|
204
|
-
};
|
|
205
|
-
const restWrapper = new RouterliciousOrdererRestWrapper(logger, rateLimiter, fetchOrdererToken, getAuthorizationHeader, useRestLess, baseurl);
|
|
189
|
+
const restWrapper = new RouterliciousOrdererRestWrapper(logger, rateLimiter, tokenFetcher, getAuthorizationHeader, useRestLess, baseurl, initialTokenP);
|
|
206
190
|
return restWrapper;
|
|
207
191
|
}
|
|
208
192
|
}
|
|
193
|
+
export function toInstrumentedR11sOrdererTokenFetcher(tenantId, documentId, tokenProvider, logger) {
|
|
194
|
+
const fetchOrdererToken = async (refreshToken) => {
|
|
195
|
+
return PerformanceEvent.timedExecAsync(logger, {
|
|
196
|
+
eventName: "FetchOrdererToken",
|
|
197
|
+
docId: documentId,
|
|
198
|
+
}, async () => {
|
|
199
|
+
const ordererToken = await tokenProvider.fetchOrdererToken(tenantId, documentId, refreshToken);
|
|
200
|
+
return ordererToken;
|
|
201
|
+
});
|
|
202
|
+
};
|
|
203
|
+
return fetchOrdererToken;
|
|
204
|
+
}
|
|
205
|
+
export function toInstrumentedR11sStorageTokenFetcher(tenantId, documentId, tokenProvider, logger) {
|
|
206
|
+
const fetchStorageToken = async (refreshToken) => {
|
|
207
|
+
return PerformanceEvent.timedExecAsync(logger, {
|
|
208
|
+
eventName: "FetchStorageToken",
|
|
209
|
+
docId: documentId,
|
|
210
|
+
}, async () => {
|
|
211
|
+
// Craft credentials using tenant id and token
|
|
212
|
+
const storageToken = await tokenProvider.fetchStorageToken(tenantId, documentId, refreshToken);
|
|
213
|
+
return storageToken;
|
|
214
|
+
});
|
|
215
|
+
};
|
|
216
|
+
return fetchStorageToken;
|
|
217
|
+
}
|
|
209
218
|
//# sourceMappingURL=restWrapper.js.map
|
package/lib/restWrapper.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"restWrapper.js","sourceRoot":"","sources":["../src/restWrapper.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, ITelemetryProperties } from \"@fluidframework/common-definitions\";\nimport { assert, fromUtf8ToBase64, performance } from \"@fluidframework/common-utils\";\nimport { RateLimiter } from \"@fluidframework/driver-utils\";\nimport {\n\tgetAuthorizationTokenFromCredentials,\n\tRestLessClient,\n} from \"@fluidframework/server-services-client\";\nimport { PerformanceEvent, TelemetryLogger } from \"@fluidframework/telemetry-utils\";\nimport fetch from \"cross-fetch\";\nimport type { AxiosRequestConfig, AxiosRequestHeaders } from \"axios\";\nimport safeStringify from \"json-stringify-safe\";\nimport { v4 as uuid } from \"uuid\";\nimport { throwR11sNetworkError } from \"./errorUtils\";\nimport { ITokenProvider, ITokenResponse } from \"./tokens\";\nimport { pkgVersion as driverVersion } from \"./packageVersion\";\nimport { QueryStringType, RestWrapper } from \"./restWrapperBase\";\n\ntype AuthorizationHeaderGetter = (token: ITokenResponse) => string;\ntype TokenFetcher = (refresh?: boolean) => Promise<ITokenResponse>;\n\nconst axiosRequestConfigToFetchRequestConfig = (\n\trequestConfig: AxiosRequestConfig,\n): [RequestInfo, RequestInit] => {\n\tconst requestInfo: string =\n\t\trequestConfig.baseURL !== undefined\n\t\t\t? `${requestConfig.baseURL}${requestConfig.url ?? \"\"}`\n\t\t\t: requestConfig.url ?? \"\";\n\tconst requestInit: RequestInit = {\n\t\tmethod: requestConfig.method,\n\t\t// NOTE: I believe that although the Axios type permits non-string values in the header, here we are\n\t\t// guaranteed the requestConfig only has string values in its header.\n\t\theaders: requestConfig.headers as Record<string, string>,\n\t\tbody: requestConfig.data,\n\t};\n\treturn [requestInfo, requestInit];\n};\n\nexport interface IR11sResponse<T> {\n\tcontent: T;\n\theaders: Map<string, string>;\n\tpropsToLog: ITelemetryProperties;\n\trequestUrl: string;\n}\n\n/**\n * A utility function to create a r11s response without any additional props as we might not have them always.\n * @param content - response which is equivalent to content.\n * @returns - a r11s response without any extra props.\n */\nexport function createR11sResponseFromContent<T>(content: T): IR11sResponse<T> {\n\treturn {\n\t\tcontent,\n\t\theaders: new Map(),\n\t\tpropsToLog: {},\n\t\trequestUrl: \"\",\n\t};\n}\n\nfunction headersToMap(headers: Headers) {\n\tconst newHeaders = new Map<string, string>();\n\tfor (const [key, value] of headers.entries()) {\n\t\tnewHeaders.set(key, value);\n\t}\n\treturn newHeaders;\n}\n\nexport function getPropsToLogFromResponse(headers: {\n\tget: (id: string) => string | undefined | null;\n}) {\n\tinterface LoggingHeader {\n\t\theaderName: string;\n\t\tlogName: string;\n\t}\n\n\t// We rename headers so that otel doesn't scrub them away. Otel doesn't allow\n\t// certain characters in headers including '-'\n\tconst headersToLog: LoggingHeader[] = [\n\t\t{ headerName: \"x-correlation-id\", logName: \"requestCorrelationId\" },\n\t\t{ headerName: \"content-encoding\", logName: \"contentEncoding\" },\n\t\t{ headerName: \"content-type\", logName: \"contentType\" },\n\t];\n\tconst additionalProps: ITelemetryProperties = {\n\t\tcontentsize: TelemetryLogger.numberFromString(headers.get(\"content-length\")),\n\t};\n\theadersToLog.forEach((header) => {\n\t\tconst headerValue = headers.get(header.headerName);\n\t\tif (headerValue !== undefined && headerValue !== null) {\n\t\t\tadditionalProps[header.logName] = headerValue;\n\t\t}\n\t});\n\n\treturn additionalProps;\n}\n\nexport class RouterliciousRestWrapper extends RestWrapper {\n\tprivate readonly restLess = new RestLessClient();\n\tprivate token: ITokenResponse | undefined;\n\n\tconstructor(\n\t\tlogger: ITelemetryLogger,\n\t\tprivate readonly rateLimiter: RateLimiter,\n\t\tprivate readonly fetchRefreshedToken: TokenFetcher,\n\t\tprivate readonly getAuthorizationHeader: AuthorizationHeaderGetter,\n\t\tprivate readonly useRestLess: boolean,\n\t\tbaseurl?: string,\n\t\tdefaultQueryString: QueryStringType = {},\n\t) {\n\t\tsuper(baseurl, defaultQueryString);\n\t}\n\n\tprotected async request<T>(\n\t\trequestConfig: AxiosRequestConfig,\n\t\tstatusCode: number,\n\t\tcanRetry = true,\n\t): Promise<IR11sResponse<T>> {\n\t\tconst config = {\n\t\t\t...requestConfig,\n\t\t\theaders: await this.generateHeaders(requestConfig.headers),\n\t\t};\n\n\t\tconst translatedConfig = this.useRestLess ? this.restLess.translate(config) : config;\n\t\tconst fetchRequestConfig = axiosRequestConfigToFetchRequestConfig(translatedConfig);\n\n\t\tconst res = await this.rateLimiter.schedule(async () => {\n\t\t\tconst perfStart = performance.now();\n\t\t\tconst result = await fetch(...fetchRequestConfig).catch(async (error) => {\n\t\t\t\t// Browser Fetch throws a TypeError on network error, `node-fetch` throws a FetchError\n\t\t\t\tconst isNetworkError = [\"TypeError\", \"FetchError\"].includes(error?.name);\n\t\t\t\tthrowR11sNetworkError(\n\t\t\t\t\tisNetworkError ? `NetworkError: ${error.message}` : safeStringify(error),\n\t\t\t\t);\n\t\t\t});\n\t\t\treturn {\n\t\t\t\tresponse: result,\n\t\t\t\tduration: performance.now() - perfStart,\n\t\t\t};\n\t\t});\n\n\t\tconst response = res.response;\n\n\t\tlet start = performance.now();\n\t\tconst text = await response.text();\n\t\tconst receiveContentTime = performance.now() - start;\n\n\t\tconst bodySize = text.length;\n\t\tstart = performance.now();\n\t\tconst responseBody: any = response.headers.get(\"content-type\")?.includes(\"application/json\")\n\t\t\t? JSON.parse(text)\n\t\t\t: text;\n\t\tconst parseTime = performance.now() - start;\n\n\t\t// Success\n\t\tif (response.ok || response.status === statusCode) {\n\t\t\tconst result = responseBody as T;\n\t\t\tconst headers = headersToMap(response.headers);\n\t\t\treturn {\n\t\t\t\tcontent: result,\n\t\t\t\theaders,\n\t\t\t\trequestUrl: fetchRequestConfig[0].toString(),\n\t\t\t\tpropsToLog: {\n\t\t\t\t\t...getPropsToLogFromResponse(headers),\n\t\t\t\t\tbodySize,\n\t\t\t\t\treceiveContentTime,\n\t\t\t\t\tparseTime,\n\t\t\t\t\tfetchTime: res.duration,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t\t// Failure\n\t\tif (response.status === 401 && canRetry) {\n\t\t\t// Refresh Authorization header and retry once\n\t\t\tthis.token = await this.fetchRefreshedToken(true /* refreshToken */);\n\t\t\treturn this.request<T>(config, statusCode, false);\n\t\t}\n\t\tif (response.status === 429 && responseBody?.retryAfter > 0) {\n\t\t\t// Retry based on retryAfter[Seconds]\n\t\t\treturn new Promise<IR11sResponse<T>>((resolve, reject) =>\n\t\t\t\tsetTimeout(() => {\n\t\t\t\t\tthis.request<T>(config, statusCode).then(resolve).catch(reject);\n\t\t\t\t}, responseBody.retryAfter * 1000),\n\t\t\t);\n\t\t}\n\n\t\tconst responseSummary =\n\t\t\tresponseBody !== undefined\n\t\t\t\t? typeof responseBody === \"string\"\n\t\t\t\t\t? responseBody\n\t\t\t\t\t: safeStringify(responseBody)\n\t\t\t\t: response.statusText;\n\t\tthrowR11sNetworkError(\n\t\t\t`R11s fetch error: ${responseSummary}`,\n\t\t\tresponse.status,\n\t\t\tresponseBody?.retryAfter,\n\t\t);\n\t}\n\n\tprivate async generateHeaders(\n\t\trequestHeaders?: AxiosRequestHeaders | undefined,\n\t): Promise<Record<string, string>> {\n\t\tconst token = await this.getToken();\n\t\tassert(token !== undefined, 0x679 /* token should be present */);\n\t\tconst correlationId = requestHeaders?.[\"x-correlation-id\"] ?? uuid();\n\n\t\treturn {\n\t\t\t...requestHeaders,\n\t\t\t// TODO: replace header names with CorrelationIdHeaderName and DriverVersionHeaderName from services-client\n\t\t\t// NOTE: Can correlationId actually be number | true?\n\t\t\t\"x-correlation-id\": correlationId as string,\n\t\t\t\"x-driver-version\": driverVersion,\n\t\t\t// NOTE: If this.authorizationHeader is undefined, should \"Authorization\" be removed entirely?\n\t\t\t\"Authorization\": this.getAuthorizationHeader(token),\n\t\t};\n\t}\n\n\tpublic async getToken(): Promise<ITokenResponse> {\n\t\tif (this.token !== undefined) {\n\t\t\treturn this.token;\n\t\t}\n\t\tconst token = await this.fetchRefreshedToken();\n\t\tthis.setToken(token);\n\t\treturn token;\n\t}\n\n\tpublic setToken(token: ITokenResponse) {\n\t\tthis.token = token;\n\t}\n}\n\nexport class RouterliciousStorageRestWrapper extends RouterliciousRestWrapper {\n\tprivate constructor(\n\t\tlogger: ITelemetryLogger,\n\t\trateLimiter: RateLimiter,\n\t\tfetchToken: TokenFetcher,\n\t\tgetAuthorizationHeader: AuthorizationHeaderGetter,\n\t\tuseRestLess: boolean,\n\t\tbaseurl?: string,\n\t\tdefaultQueryString: QueryStringType = {},\n\t) {\n\t\tsuper(\n\t\t\tlogger,\n\t\t\trateLimiter,\n\t\t\tfetchToken,\n\t\t\tgetAuthorizationHeader,\n\t\t\tuseRestLess,\n\t\t\tbaseurl,\n\t\t\tdefaultQueryString,\n\t\t);\n\t}\n\n\tpublic static async load(\n\t\ttenantId: string,\n\t\tdocumentId: string,\n\t\ttokenProvider: ITokenProvider,\n\t\tlogger: ITelemetryLogger,\n\t\trateLimiter: RateLimiter,\n\t\tuseRestLess: boolean,\n\t\tbaseurl?: string,\n\t): Promise<RouterliciousStorageRestWrapper> {\n\t\tconst defaultQueryString = {\n\t\t\ttoken: `${fromUtf8ToBase64(tenantId)}`,\n\t\t};\n\n\t\tconst fetchStorageToken = async (refreshToken?: boolean): Promise<ITokenResponse> => {\n\t\t\treturn PerformanceEvent.timedExecAsync(\n\t\t\t\tlogger,\n\t\t\t\t{\n\t\t\t\t\teventName: \"FetchStorageToken\",\n\t\t\t\t\tdocId: documentId,\n\t\t\t\t},\n\t\t\t\tasync () => {\n\t\t\t\t\t// Craft credentials using tenant id and token\n\t\t\t\t\tconst storageToken = await tokenProvider.fetchStorageToken(\n\t\t\t\t\t\ttenantId,\n\t\t\t\t\t\tdocumentId,\n\t\t\t\t\t\trefreshToken,\n\t\t\t\t\t);\n\n\t\t\t\t\treturn storageToken;\n\t\t\t\t},\n\t\t\t);\n\t\t};\n\n\t\tconst getAuthorizationHeader: AuthorizationHeaderGetter = (\n\t\t\ttoken: ITokenResponse,\n\t\t): string => {\n\t\t\tconst credentials = {\n\t\t\t\tpassword: token.jwt,\n\t\t\t\tuser: tenantId,\n\t\t\t};\n\t\t\treturn getAuthorizationTokenFromCredentials(credentials);\n\t\t};\n\n\t\tconst restWrapper = new RouterliciousStorageRestWrapper(\n\t\t\tlogger,\n\t\t\trateLimiter,\n\t\t\tfetchStorageToken,\n\t\t\tgetAuthorizationHeader,\n\t\t\tuseRestLess,\n\t\t\tbaseurl,\n\t\t\tdefaultQueryString,\n\t\t);\n\n\t\treturn restWrapper;\n\t}\n}\n\nexport class RouterliciousOrdererRestWrapper extends RouterliciousRestWrapper {\n\tprivate constructor(\n\t\tlogger: ITelemetryLogger,\n\t\trateLimiter: RateLimiter,\n\t\tfetchToken: TokenFetcher,\n\t\tgetAuthorizationHeader: AuthorizationHeaderGetter,\n\t\tuseRestLess: boolean,\n\t\tbaseurl?: string,\n\t\tdefaultQueryString: QueryStringType = {},\n\t) {\n\t\tsuper(\n\t\t\tlogger,\n\t\t\trateLimiter,\n\t\t\tfetchToken,\n\t\t\tgetAuthorizationHeader,\n\t\t\tuseRestLess,\n\t\t\tbaseurl,\n\t\t\tdefaultQueryString,\n\t\t);\n\t}\n\n\tpublic static async load(\n\t\ttenantId: string,\n\t\tdocumentId: string | undefined,\n\t\ttokenProvider: ITokenProvider,\n\t\tlogger: ITelemetryLogger,\n\t\trateLimiter: RateLimiter,\n\t\tuseRestLess: boolean,\n\t\tbaseurl?: string,\n\t): Promise<RouterliciousOrdererRestWrapper> {\n\t\tconst getAuthorizationHeader: AuthorizationHeaderGetter = (\n\t\t\ttoken: ITokenResponse,\n\t\t): string => {\n\t\t\treturn `Basic ${token.jwt}`;\n\t\t};\n\n\t\tconst fetchOrdererToken = async (refreshToken?: boolean): Promise<ITokenResponse> => {\n\t\t\treturn PerformanceEvent.timedExecAsync(\n\t\t\t\tlogger,\n\t\t\t\t{\n\t\t\t\t\teventName: \"FetchOrdererToken\",\n\t\t\t\t\tdocId: documentId,\n\t\t\t\t},\n\t\t\t\tasync () => {\n\t\t\t\t\tconst ordererToken = await tokenProvider.fetchOrdererToken(\n\t\t\t\t\t\ttenantId,\n\t\t\t\t\t\tdocumentId,\n\t\t\t\t\t\trefreshToken,\n\t\t\t\t\t);\n\n\t\t\t\t\treturn ordererToken;\n\t\t\t\t},\n\t\t\t);\n\t\t};\n\n\t\tconst restWrapper = new RouterliciousOrdererRestWrapper(\n\t\t\tlogger,\n\t\t\trateLimiter,\n\t\t\tfetchOrdererToken,\n\t\t\tgetAuthorizationHeader,\n\t\t\tuseRestLess,\n\t\t\tbaseurl,\n\t\t);\n\n\t\treturn restWrapper;\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"restWrapper.js","sourceRoot":"","sources":["../src/restWrapper.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, ITelemetryProperties } from \"@fluidframework/common-definitions\";\nimport { assert, fromUtf8ToBase64, performance } from \"@fluidframework/common-utils\";\nimport { RateLimiter } from \"@fluidframework/driver-utils\";\nimport {\n\tgetAuthorizationTokenFromCredentials,\n\tRestLessClient,\n} from \"@fluidframework/server-services-client\";\nimport { PerformanceEvent, TelemetryLogger } from \"@fluidframework/telemetry-utils\";\nimport fetch from \"cross-fetch\";\nimport type { AxiosRequestConfig, AxiosRequestHeaders } from \"axios\";\nimport safeStringify from \"json-stringify-safe\";\nimport { v4 as uuid } from \"uuid\";\nimport { throwR11sNetworkError } from \"./errorUtils\";\nimport { ITokenProvider, ITokenResponse } from \"./tokens\";\nimport { pkgVersion as driverVersion } from \"./packageVersion\";\nimport { QueryStringType, RestWrapper } from \"./restWrapperBase\";\n\ntype AuthorizationHeaderGetter = (token: ITokenResponse) => string;\nexport type TokenFetcher = (refresh?: boolean) => Promise<ITokenResponse>;\n\nconst axiosRequestConfigToFetchRequestConfig = (\n\trequestConfig: AxiosRequestConfig,\n): [RequestInfo, RequestInit] => {\n\tconst requestInfo: string =\n\t\trequestConfig.baseURL !== undefined\n\t\t\t? `${requestConfig.baseURL}${requestConfig.url ?? \"\"}`\n\t\t\t: requestConfig.url ?? \"\";\n\tconst requestInit: RequestInit = {\n\t\tmethod: requestConfig.method,\n\t\t// NOTE: I believe that although the Axios type permits non-string values in the header, here we are\n\t\t// guaranteed the requestConfig only has string values in its header.\n\t\theaders: requestConfig.headers as Record<string, string>,\n\t\tbody: requestConfig.data,\n\t};\n\treturn [requestInfo, requestInit];\n};\n\nexport interface IR11sResponse<T> {\n\tcontent: T;\n\theaders: Map<string, string>;\n\tpropsToLog: ITelemetryProperties;\n\trequestUrl: string;\n}\n\n/**\n * A utility function to create a r11s response without any additional props as we might not have them always.\n * @param content - response which is equivalent to content.\n * @returns - a r11s response without any extra props.\n */\nexport function createR11sResponseFromContent<T>(content: T): IR11sResponse<T> {\n\treturn {\n\t\tcontent,\n\t\theaders: new Map(),\n\t\tpropsToLog: {},\n\t\trequestUrl: \"\",\n\t};\n}\n\nfunction headersToMap(headers: Headers) {\n\tconst newHeaders = new Map<string, string>();\n\tfor (const [key, value] of headers.entries()) {\n\t\tnewHeaders.set(key, value);\n\t}\n\treturn newHeaders;\n}\n\nexport function getPropsToLogFromResponse(headers: {\n\tget: (id: string) => string | undefined | null;\n}) {\n\tinterface LoggingHeader {\n\t\theaderName: string;\n\t\tlogName: string;\n\t}\n\n\t// We rename headers so that otel doesn't scrub them away. Otel doesn't allow\n\t// certain characters in headers including '-'\n\tconst headersToLog: LoggingHeader[] = [\n\t\t{ headerName: \"x-correlation-id\", logName: \"requestCorrelationId\" },\n\t\t{ headerName: \"content-encoding\", logName: \"contentEncoding\" },\n\t\t{ headerName: \"content-type\", logName: \"contentType\" },\n\t];\n\tconst additionalProps: ITelemetryProperties = {\n\t\tcontentsize: TelemetryLogger.numberFromString(headers.get(\"content-length\")),\n\t};\n\theadersToLog.forEach((header) => {\n\t\tconst headerValue = headers.get(header.headerName);\n\t\tif (headerValue !== undefined && headerValue !== null) {\n\t\t\tadditionalProps[header.logName] = headerValue;\n\t\t}\n\t});\n\n\treturn additionalProps;\n}\n\nexport class RouterliciousRestWrapper extends RestWrapper {\n\tprivate readonly restLess = new RestLessClient();\n\tprivate token: ITokenResponse | undefined;\n\n\tconstructor(\n\t\tlogger: ITelemetryLogger,\n\t\tprivate readonly rateLimiter: RateLimiter,\n\t\tprivate readonly fetchRefreshedToken: TokenFetcher,\n\t\tprivate readonly getAuthorizationHeader: AuthorizationHeaderGetter,\n\t\tprivate readonly useRestLess: boolean,\n\t\tbaseurl?: string,\n\t\tprivate tokenP?: Promise<ITokenResponse>,\n\t\tdefaultQueryString: QueryStringType = {},\n\t) {\n\t\tsuper(baseurl, defaultQueryString);\n\t}\n\n\tprotected async request<T>(\n\t\trequestConfig: AxiosRequestConfig,\n\t\tstatusCode: number,\n\t\tcanRetry = true,\n\t): Promise<IR11sResponse<T>> {\n\t\tconst config = {\n\t\t\t...requestConfig,\n\t\t\theaders: await this.generateHeaders(requestConfig.headers),\n\t\t};\n\n\t\tconst translatedConfig = this.useRestLess ? this.restLess.translate(config) : config;\n\t\tconst fetchRequestConfig = axiosRequestConfigToFetchRequestConfig(translatedConfig);\n\n\t\tconst res = await this.rateLimiter.schedule(async () => {\n\t\t\tconst perfStart = performance.now();\n\t\t\tconst result = await fetch(...fetchRequestConfig).catch(async (error) => {\n\t\t\t\t// Browser Fetch throws a TypeError on network error, `node-fetch` throws a FetchError\n\t\t\t\tconst isNetworkError = [\"TypeError\", \"FetchError\"].includes(error?.name);\n\t\t\t\tthrowR11sNetworkError(\n\t\t\t\t\tisNetworkError ? `NetworkError: ${error.message}` : safeStringify(error),\n\t\t\t\t);\n\t\t\t});\n\t\t\treturn {\n\t\t\t\tresponse: result,\n\t\t\t\tduration: performance.now() - perfStart,\n\t\t\t};\n\t\t});\n\n\t\tconst response = res.response;\n\n\t\tlet start = performance.now();\n\t\tconst text = await response.text();\n\t\tconst receiveContentTime = performance.now() - start;\n\n\t\tconst bodySize = text.length;\n\t\tstart = performance.now();\n\t\tconst responseBody: any = response.headers.get(\"content-type\")?.includes(\"application/json\")\n\t\t\t? JSON.parse(text)\n\t\t\t: text;\n\t\tconst parseTime = performance.now() - start;\n\n\t\t// Success\n\t\tif (response.ok || response.status === statusCode) {\n\t\t\tconst result = responseBody as T;\n\t\t\tconst headers = headersToMap(response.headers);\n\t\t\treturn {\n\t\t\t\tcontent: result,\n\t\t\t\theaders,\n\t\t\t\trequestUrl: fetchRequestConfig[0].toString(),\n\t\t\t\tpropsToLog: {\n\t\t\t\t\t...getPropsToLogFromResponse(headers),\n\t\t\t\t\tbodySize,\n\t\t\t\t\treceiveContentTime,\n\t\t\t\t\tparseTime,\n\t\t\t\t\tfetchTime: res.duration,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t\t// Failure\n\t\tif (response.status === 401 && canRetry) {\n\t\t\t// Refresh Authorization header and retry once\n\t\t\tthis.token = await this.fetchRefreshedToken(true /* refreshToken */);\n\t\t\treturn this.request<T>(config, statusCode, false);\n\t\t}\n\t\tif (response.status === 429 && responseBody?.retryAfter > 0) {\n\t\t\t// Retry based on retryAfter[Seconds]\n\t\t\treturn new Promise<IR11sResponse<T>>((resolve, reject) =>\n\t\t\t\tsetTimeout(() => {\n\t\t\t\t\tthis.request<T>(config, statusCode).then(resolve).catch(reject);\n\t\t\t\t}, responseBody.retryAfter * 1000),\n\t\t\t);\n\t\t}\n\n\t\tconst responseSummary =\n\t\t\tresponseBody !== undefined\n\t\t\t\t? typeof responseBody === \"string\"\n\t\t\t\t\t? responseBody\n\t\t\t\t\t: safeStringify(responseBody)\n\t\t\t\t: response.statusText;\n\t\tthrowR11sNetworkError(\n\t\t\t`R11s fetch error: ${responseSummary}`,\n\t\t\tresponse.status,\n\t\t\tresponseBody?.retryAfter,\n\t\t);\n\t}\n\n\tprivate async generateHeaders(\n\t\trequestHeaders?: AxiosRequestHeaders | undefined,\n\t): Promise<Record<string, string>> {\n\t\tconst token = await this.getToken();\n\t\tassert(token !== undefined, 0x679 /* token should be present */);\n\t\tconst correlationId = requestHeaders?.[\"x-correlation-id\"] ?? uuid();\n\n\t\treturn {\n\t\t\t...requestHeaders,\n\t\t\t// TODO: replace header names with CorrelationIdHeaderName and DriverVersionHeaderName from services-client\n\t\t\t// NOTE: Can correlationId actually be number | true?\n\t\t\t\"x-correlation-id\": correlationId as string,\n\t\t\t\"x-driver-version\": driverVersion,\n\t\t\t// NOTE: If this.authorizationHeader is undefined, should \"Authorization\" be removed entirely?\n\t\t\t\"Authorization\": this.getAuthorizationHeader(token),\n\t\t};\n\t}\n\n\tpublic async getToken(): Promise<ITokenResponse> {\n\t\tif (this.token !== undefined) {\n\t\t\treturn this.token;\n\t\t}\n\t\tconst token = await (this.tokenP ?? this.fetchRefreshedToken());\n\t\tthis.setToken(token);\n\t\tthis.tokenP = undefined;\n\t\treturn token;\n\t}\n\n\tpublic setToken(token: ITokenResponse) {\n\t\tthis.token = token;\n\t}\n}\n\nexport class RouterliciousStorageRestWrapper extends RouterliciousRestWrapper {\n\tprivate constructor(\n\t\tlogger: ITelemetryLogger,\n\t\trateLimiter: RateLimiter,\n\t\tfetchToken: TokenFetcher,\n\t\tgetAuthorizationHeader: AuthorizationHeaderGetter,\n\t\tuseRestLess: boolean,\n\t\tbaseurl?: string,\n\t\tinitialTokenP?: Promise<ITokenResponse>,\n\t\tdefaultQueryString: QueryStringType = {},\n\t) {\n\t\tsuper(\n\t\t\tlogger,\n\t\t\trateLimiter,\n\t\t\tfetchToken,\n\t\t\tgetAuthorizationHeader,\n\t\t\tuseRestLess,\n\t\t\tbaseurl,\n\t\t\tinitialTokenP,\n\t\t\tdefaultQueryString,\n\t\t);\n\t}\n\n\tpublic static async load(\n\t\ttenantId: string,\n\t\ttokenFetcher: TokenFetcher,\n\t\tlogger: ITelemetryLogger,\n\t\trateLimiter: RateLimiter,\n\t\tuseRestLess: boolean,\n\t\tbaseurl?: string,\n\t\tinitialTokenP?: Promise<ITokenResponse>,\n\t): Promise<RouterliciousStorageRestWrapper> {\n\t\tconst defaultQueryString = {\n\t\t\ttoken: `${fromUtf8ToBase64(tenantId)}`,\n\t\t};\n\n\t\tconst getAuthorizationHeader: AuthorizationHeaderGetter = (\n\t\t\ttoken: ITokenResponse,\n\t\t): string => {\n\t\t\tconst credentials = {\n\t\t\t\tpassword: token.jwt,\n\t\t\t\tuser: tenantId,\n\t\t\t};\n\t\t\treturn getAuthorizationTokenFromCredentials(credentials);\n\t\t};\n\n\t\tconst restWrapper = new RouterliciousStorageRestWrapper(\n\t\t\tlogger,\n\t\t\trateLimiter,\n\t\t\ttokenFetcher,\n\t\t\tgetAuthorizationHeader,\n\t\t\tuseRestLess,\n\t\t\tbaseurl,\n\t\t\tinitialTokenP,\n\t\t\tdefaultQueryString,\n\t\t);\n\n\t\treturn restWrapper;\n\t}\n}\n\nexport class RouterliciousOrdererRestWrapper extends RouterliciousRestWrapper {\n\tprivate constructor(\n\t\tlogger: ITelemetryLogger,\n\t\trateLimiter: RateLimiter,\n\t\tfetchToken: TokenFetcher,\n\t\tgetAuthorizationHeader: AuthorizationHeaderGetter,\n\t\tuseRestLess: boolean,\n\t\tbaseurl?: string,\n\t\tinitialTokenP?: Promise<ITokenResponse>,\n\t\tdefaultQueryString: QueryStringType = {},\n\t) {\n\t\tsuper(\n\t\t\tlogger,\n\t\t\trateLimiter,\n\t\t\tfetchToken,\n\t\t\tgetAuthorizationHeader,\n\t\t\tuseRestLess,\n\t\t\tbaseurl,\n\t\t\tinitialTokenP,\n\t\t\tdefaultQueryString,\n\t\t);\n\t}\n\n\tpublic static async load(\n\t\ttokenFetcher: TokenFetcher,\n\t\tlogger: ITelemetryLogger,\n\t\trateLimiter: RateLimiter,\n\t\tuseRestLess: boolean,\n\t\tbaseurl?: string,\n\t\tinitialTokenP?: Promise<ITokenResponse>,\n\t): Promise<RouterliciousOrdererRestWrapper> {\n\t\tconst getAuthorizationHeader: AuthorizationHeaderGetter = (\n\t\t\ttoken: ITokenResponse,\n\t\t): string => {\n\t\t\treturn `Basic ${token.jwt}`;\n\t\t};\n\n\t\tconst restWrapper = new RouterliciousOrdererRestWrapper(\n\t\t\tlogger,\n\t\t\trateLimiter,\n\t\t\ttokenFetcher,\n\t\t\tgetAuthorizationHeader,\n\t\t\tuseRestLess,\n\t\t\tbaseurl,\n\t\t\tinitialTokenP,\n\t\t);\n\n\t\treturn restWrapper;\n\t}\n}\n\nexport function toInstrumentedR11sOrdererTokenFetcher(\n\ttenantId: string,\n\tdocumentId: string | undefined,\n\ttokenProvider: ITokenProvider,\n\tlogger: ITelemetryLogger,\n): TokenFetcher {\n\tconst fetchOrdererToken = async (refreshToken?: boolean): Promise<ITokenResponse> => {\n\t\treturn PerformanceEvent.timedExecAsync(\n\t\t\tlogger,\n\t\t\t{\n\t\t\t\teventName: \"FetchOrdererToken\",\n\t\t\t\tdocId: documentId,\n\t\t\t},\n\t\t\tasync () => {\n\t\t\t\tconst ordererToken = await tokenProvider.fetchOrdererToken(\n\t\t\t\t\ttenantId,\n\t\t\t\t\tdocumentId,\n\t\t\t\t\trefreshToken,\n\t\t\t\t);\n\n\t\t\t\treturn ordererToken;\n\t\t\t},\n\t\t);\n\t};\n\treturn fetchOrdererToken;\n}\n\nexport function toInstrumentedR11sStorageTokenFetcher(\n\ttenantId: string,\n\tdocumentId: string,\n\ttokenProvider: ITokenProvider,\n\tlogger: ITelemetryLogger,\n): TokenFetcher {\n\tconst fetchStorageToken = async (refreshToken?: boolean): Promise<ITokenResponse> => {\n\t\treturn PerformanceEvent.timedExecAsync(\n\t\t\tlogger,\n\t\t\t{\n\t\t\t\teventName: \"FetchStorageToken\",\n\t\t\t\tdocId: documentId,\n\t\t\t},\n\t\t\tasync () => {\n\t\t\t\t// Craft credentials using tenant id and token\n\t\t\t\tconst storageToken = await tokenProvider.fetchStorageToken(\n\t\t\t\t\ttenantId,\n\t\t\t\t\tdocumentId,\n\t\t\t\t\trefreshToken,\n\t\t\t\t);\n\n\t\t\t\treturn storageToken;\n\t\t\t},\n\t\t);\n\t};\n\treturn fetchStorageToken;\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fluidframework/routerlicious-driver",
|
|
3
|
-
"version": "2.0.0-dev.4.4.0.
|
|
3
|
+
"version": "2.0.0-dev.4.4.0.162574",
|
|
4
4
|
"description": "Socket.IO + Git implementation of Fluid service API",
|
|
5
5
|
"homepage": "https://fluidframework.com",
|
|
6
6
|
"repository": {
|
|
@@ -37,14 +37,14 @@
|
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"@fluidframework/common-definitions": "^0.20.1",
|
|
39
39
|
"@fluidframework/common-utils": "^1.1.1",
|
|
40
|
-
"@fluidframework/driver-base": "2.0.0-dev.4.4.0.
|
|
41
|
-
"@fluidframework/driver-definitions": "2.0.0-dev.4.4.0.
|
|
42
|
-
"@fluidframework/driver-utils": "2.0.0-dev.4.4.0.
|
|
40
|
+
"@fluidframework/driver-base": "2.0.0-dev.4.4.0.162574",
|
|
41
|
+
"@fluidframework/driver-definitions": "2.0.0-dev.4.4.0.162574",
|
|
42
|
+
"@fluidframework/driver-utils": "2.0.0-dev.4.4.0.162574",
|
|
43
43
|
"@fluidframework/gitresources": "^0.1039.1000",
|
|
44
44
|
"@fluidframework/protocol-base": "^0.1039.1000",
|
|
45
45
|
"@fluidframework/protocol-definitions": "^1.1.0",
|
|
46
46
|
"@fluidframework/server-services-client": "^0.1039.1000",
|
|
47
|
-
"@fluidframework/telemetry-utils": "2.0.0-dev.4.4.0.
|
|
47
|
+
"@fluidframework/telemetry-utils": "2.0.0-dev.4.4.0.162574",
|
|
48
48
|
"cross-fetch": "^3.1.5",
|
|
49
49
|
"json-stringify-safe": "5.0.1",
|
|
50
50
|
"socket.io-client": "^4.4.1",
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
"@fluidframework/build-common": "^1.1.0",
|
|
57
57
|
"@fluidframework/build-tools": "^0.17.0",
|
|
58
58
|
"@fluidframework/eslint-config-fluid": "^2.0.0",
|
|
59
|
-
"@fluidframework/mocha-test-setup": "2.0.0-dev.4.4.0.
|
|
59
|
+
"@fluidframework/mocha-test-setup": "2.0.0-dev.4.4.0.162574",
|
|
60
60
|
"@fluidframework/routerlicious-driver-previous": "npm:@fluidframework/routerlicious-driver@2.0.0-internal.4.1.0",
|
|
61
61
|
"@microsoft/api-extractor": "^7.34.4",
|
|
62
62
|
"@types/mocha": "^9.1.1",
|
package/src/documentService.ts
CHANGED
|
@@ -16,7 +16,11 @@ import { DocumentStorageService } from "./documentStorageService";
|
|
|
16
16
|
import { R11sDocumentDeltaConnection } from "./documentDeltaConnection";
|
|
17
17
|
import { NullBlobStorageService } from "./nullBlobStorageService";
|
|
18
18
|
import { ITokenProvider } from "./tokens";
|
|
19
|
-
import {
|
|
19
|
+
import {
|
|
20
|
+
RouterliciousOrdererRestWrapper,
|
|
21
|
+
RouterliciousStorageRestWrapper,
|
|
22
|
+
TokenFetcher,
|
|
23
|
+
} from "./restWrapper";
|
|
20
24
|
import { IRouterliciousDriverPolicies } from "./policies";
|
|
21
25
|
import { ICache } from "./cache";
|
|
22
26
|
import { ISnapshotTreeVersion } from "./definitions";
|
|
@@ -67,6 +71,9 @@ export class DocumentService implements api.IDocumentService {
|
|
|
67
71
|
private readonly wholeSnapshotTreeCache: ICache<INormalizedWholeSummary>,
|
|
68
72
|
private readonly shreddedSummaryTreeCache: ICache<ISnapshotTreeVersion>,
|
|
69
73
|
private readonly discoverFluidResolvedUrl: () => Promise<api.IFluidResolvedUrl>,
|
|
74
|
+
private storageRestWrapper: RouterliciousStorageRestWrapper,
|
|
75
|
+
private readonly storageTokenFetcher: TokenFetcher,
|
|
76
|
+
private readonly ordererTokenFetcher: TokenFetcher,
|
|
70
77
|
) {}
|
|
71
78
|
|
|
72
79
|
private documentStorageService: DocumentStorageService | undefined;
|
|
@@ -97,21 +104,22 @@ export class DocumentService implements api.IDocumentService {
|
|
|
97
104
|
!this.noCacheStorageManager ||
|
|
98
105
|
shouldUpdateDiscoveredSessionInfo
|
|
99
106
|
) {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
this.
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
107
|
+
if (shouldUpdateDiscoveredSessionInfo) {
|
|
108
|
+
const rateLimiter = new RateLimiter(
|
|
109
|
+
this.driverPolicies.maxConcurrentStorageRequests,
|
|
110
|
+
);
|
|
111
|
+
this.storageRestWrapper = await RouterliciousStorageRestWrapper.load(
|
|
112
|
+
this.tenantId,
|
|
113
|
+
this.storageTokenFetcher,
|
|
114
|
+
this.logger,
|
|
115
|
+
rateLimiter,
|
|
116
|
+
this.driverPolicies.enableRestLess,
|
|
117
|
+
this.storageUrl,
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
const historian = new Historian(true, false, this.storageRestWrapper);
|
|
113
121
|
this.storageManager = new GitManager(historian);
|
|
114
|
-
const noCacheHistorian = new Historian(true, true, storageRestWrapper);
|
|
122
|
+
const noCacheHistorian = new Historian(true, true, this.storageRestWrapper);
|
|
115
123
|
this.noCacheStorageManager = new GitManager(noCacheHistorian);
|
|
116
124
|
}
|
|
117
125
|
|
|
@@ -153,9 +161,7 @@ export class DocumentService implements api.IDocumentService {
|
|
|
153
161
|
this.driverPolicies.maxConcurrentOrdererRequests,
|
|
154
162
|
);
|
|
155
163
|
this.ordererRestWrapper = await RouterliciousOrdererRestWrapper.load(
|
|
156
|
-
this.
|
|
157
|
-
this.documentId,
|
|
158
|
-
this.tokenProvider,
|
|
164
|
+
this.ordererTokenFetcher,
|
|
159
165
|
this.logger,
|
|
160
166
|
rateLimiter,
|
|
161
167
|
this.driverPolicies.enableRestLess,
|
|
@@ -28,7 +28,12 @@ import { ISession } from "@fluidframework/server-services-client";
|
|
|
28
28
|
import { DocumentService } from "./documentService";
|
|
29
29
|
import { IRouterliciousDriverPolicies } from "./policies";
|
|
30
30
|
import { ITokenProvider } from "./tokens";
|
|
31
|
-
import {
|
|
31
|
+
import {
|
|
32
|
+
RouterliciousOrdererRestWrapper,
|
|
33
|
+
RouterliciousStorageRestWrapper,
|
|
34
|
+
toInstrumentedR11sOrdererTokenFetcher,
|
|
35
|
+
toInstrumentedR11sStorageTokenFetcher,
|
|
36
|
+
} from "./restWrapper";
|
|
32
37
|
import { convertSummaryToCreateNewSummary } from "./createNewUtils";
|
|
33
38
|
import { parseFluidUrl, replaceDocumentIdInPath, getDiscoveredFluidResolvedUrl } from "./urlUtils";
|
|
34
39
|
import { ICache, InMemoryCache, NullCache } from "./cache";
|
|
@@ -117,12 +122,16 @@ export class RouterliciousDocumentServiceFactory implements IDocumentServiceFact
|
|
|
117
122
|
const quorumValues = getQuorumValuesFromProtocolSummary(protocolSummary);
|
|
118
123
|
|
|
119
124
|
const logger2 = ChildLogger.create(logger, "RouterliciousDriver");
|
|
120
|
-
const
|
|
121
|
-
const ordererRestWrapper = await RouterliciousOrdererRestWrapper.load(
|
|
125
|
+
const ordererTokenFetcher = toInstrumentedR11sOrdererTokenFetcher(
|
|
122
126
|
tenantId,
|
|
123
|
-
undefined
|
|
127
|
+
undefined /* documentId */,
|
|
124
128
|
this.tokenProvider,
|
|
125
129
|
logger2,
|
|
130
|
+
);
|
|
131
|
+
const rateLimiter = new RateLimiter(this.driverPolicies.maxConcurrentOrdererRequests);
|
|
132
|
+
const ordererRestWrapper = await RouterliciousOrdererRestWrapper.load(
|
|
133
|
+
ordererTokenFetcher,
|
|
134
|
+
logger2,
|
|
126
135
|
rateLimiter,
|
|
127
136
|
this.driverPolicies.enableRestLess,
|
|
128
137
|
resolvedUrl.endpoints.ordererUrl,
|
|
@@ -245,14 +254,29 @@ export class RouterliciousDocumentServiceFactory implements IDocumentServiceFact
|
|
|
245
254
|
all: { driverVersion },
|
|
246
255
|
});
|
|
247
256
|
|
|
248
|
-
const
|
|
249
|
-
const ordererRestWrapper = await RouterliciousOrdererRestWrapper.load(
|
|
257
|
+
const ordererTokenFetcher = toInstrumentedR11sOrdererTokenFetcher(
|
|
250
258
|
tenantId,
|
|
251
259
|
documentId,
|
|
252
260
|
this.tokenProvider,
|
|
253
261
|
logger2,
|
|
262
|
+
);
|
|
263
|
+
const storageTokenFetcher = toInstrumentedR11sStorageTokenFetcher(
|
|
264
|
+
tenantId,
|
|
265
|
+
documentId,
|
|
266
|
+
this.tokenProvider,
|
|
267
|
+
logger2,
|
|
268
|
+
);
|
|
269
|
+
const ordererTokenP = ordererTokenFetcher();
|
|
270
|
+
const storageTokenP = storageTokenFetcher();
|
|
271
|
+
|
|
272
|
+
const rateLimiter = new RateLimiter(this.driverPolicies.maxConcurrentOrdererRequests);
|
|
273
|
+
const ordererRestWrapper = await RouterliciousOrdererRestWrapper.load(
|
|
274
|
+
ordererTokenFetcher,
|
|
275
|
+
logger2,
|
|
254
276
|
rateLimiter,
|
|
255
277
|
this.driverPolicies.enableRestLess,
|
|
278
|
+
undefined /* baseUrl */,
|
|
279
|
+
ordererTokenP,
|
|
256
280
|
);
|
|
257
281
|
|
|
258
282
|
const discoverFluidResolvedUrl = async (): Promise<IFluidResolvedUrl> => {
|
|
@@ -295,6 +319,16 @@ export class RouterliciousDocumentServiceFactory implements IDocumentServiceFact
|
|
|
295
319
|
);
|
|
296
320
|
}
|
|
297
321
|
|
|
322
|
+
const storageRestWrapper = await RouterliciousStorageRestWrapper.load(
|
|
323
|
+
tenantId,
|
|
324
|
+
storageTokenFetcher,
|
|
325
|
+
logger2,
|
|
326
|
+
new RateLimiter(this.driverPolicies.maxConcurrentStorageRequests),
|
|
327
|
+
this.driverPolicies.enableRestLess,
|
|
328
|
+
storageUrl,
|
|
329
|
+
storageTokenP,
|
|
330
|
+
);
|
|
331
|
+
|
|
298
332
|
const documentStorageServicePolicies: IDocumentStorageServicePolicies = {
|
|
299
333
|
caching: this.driverPolicies.enablePrefetch
|
|
300
334
|
? LoaderCachingPolicy.Prefetch
|
|
@@ -320,6 +354,9 @@ export class RouterliciousDocumentServiceFactory implements IDocumentServiceFact
|
|
|
320
354
|
this.wholeSnapshotTreeCache,
|
|
321
355
|
this.shreddedSummaryTreeCache,
|
|
322
356
|
discoverFluidResolvedUrl,
|
|
357
|
+
storageRestWrapper,
|
|
358
|
+
storageTokenFetcher,
|
|
359
|
+
ordererTokenFetcher,
|
|
323
360
|
);
|
|
324
361
|
}
|
|
325
362
|
}
|
package/src/packageVersion.ts
CHANGED
package/src/restWrapper.ts
CHANGED
|
@@ -21,7 +21,7 @@ import { pkgVersion as driverVersion } from "./packageVersion";
|
|
|
21
21
|
import { QueryStringType, RestWrapper } from "./restWrapperBase";
|
|
22
22
|
|
|
23
23
|
type AuthorizationHeaderGetter = (token: ITokenResponse) => string;
|
|
24
|
-
type TokenFetcher = (refresh?: boolean) => Promise<ITokenResponse>;
|
|
24
|
+
export type TokenFetcher = (refresh?: boolean) => Promise<ITokenResponse>;
|
|
25
25
|
|
|
26
26
|
const axiosRequestConfigToFetchRequestConfig = (
|
|
27
27
|
requestConfig: AxiosRequestConfig,
|
|
@@ -108,6 +108,7 @@ export class RouterliciousRestWrapper extends RestWrapper {
|
|
|
108
108
|
private readonly getAuthorizationHeader: AuthorizationHeaderGetter,
|
|
109
109
|
private readonly useRestLess: boolean,
|
|
110
110
|
baseurl?: string,
|
|
111
|
+
private tokenP?: Promise<ITokenResponse>,
|
|
111
112
|
defaultQueryString: QueryStringType = {},
|
|
112
113
|
) {
|
|
113
114
|
super(baseurl, defaultQueryString);
|
|
@@ -221,8 +222,9 @@ export class RouterliciousRestWrapper extends RestWrapper {
|
|
|
221
222
|
if (this.token !== undefined) {
|
|
222
223
|
return this.token;
|
|
223
224
|
}
|
|
224
|
-
const token = await this.fetchRefreshedToken();
|
|
225
|
+
const token = await (this.tokenP ?? this.fetchRefreshedToken());
|
|
225
226
|
this.setToken(token);
|
|
227
|
+
this.tokenP = undefined;
|
|
226
228
|
return token;
|
|
227
229
|
}
|
|
228
230
|
|
|
@@ -239,6 +241,7 @@ export class RouterliciousStorageRestWrapper extends RouterliciousRestWrapper {
|
|
|
239
241
|
getAuthorizationHeader: AuthorizationHeaderGetter,
|
|
240
242
|
useRestLess: boolean,
|
|
241
243
|
baseurl?: string,
|
|
244
|
+
initialTokenP?: Promise<ITokenResponse>,
|
|
242
245
|
defaultQueryString: QueryStringType = {},
|
|
243
246
|
) {
|
|
244
247
|
super(
|
|
@@ -248,43 +251,24 @@ export class RouterliciousStorageRestWrapper extends RouterliciousRestWrapper {
|
|
|
248
251
|
getAuthorizationHeader,
|
|
249
252
|
useRestLess,
|
|
250
253
|
baseurl,
|
|
254
|
+
initialTokenP,
|
|
251
255
|
defaultQueryString,
|
|
252
256
|
);
|
|
253
257
|
}
|
|
254
258
|
|
|
255
259
|
public static async load(
|
|
256
260
|
tenantId: string,
|
|
257
|
-
|
|
258
|
-
tokenProvider: ITokenProvider,
|
|
261
|
+
tokenFetcher: TokenFetcher,
|
|
259
262
|
logger: ITelemetryLogger,
|
|
260
263
|
rateLimiter: RateLimiter,
|
|
261
264
|
useRestLess: boolean,
|
|
262
265
|
baseurl?: string,
|
|
266
|
+
initialTokenP?: Promise<ITokenResponse>,
|
|
263
267
|
): Promise<RouterliciousStorageRestWrapper> {
|
|
264
268
|
const defaultQueryString = {
|
|
265
269
|
token: `${fromUtf8ToBase64(tenantId)}`,
|
|
266
270
|
};
|
|
267
271
|
|
|
268
|
-
const fetchStorageToken = async (refreshToken?: boolean): Promise<ITokenResponse> => {
|
|
269
|
-
return PerformanceEvent.timedExecAsync(
|
|
270
|
-
logger,
|
|
271
|
-
{
|
|
272
|
-
eventName: "FetchStorageToken",
|
|
273
|
-
docId: documentId,
|
|
274
|
-
},
|
|
275
|
-
async () => {
|
|
276
|
-
// Craft credentials using tenant id and token
|
|
277
|
-
const storageToken = await tokenProvider.fetchStorageToken(
|
|
278
|
-
tenantId,
|
|
279
|
-
documentId,
|
|
280
|
-
refreshToken,
|
|
281
|
-
);
|
|
282
|
-
|
|
283
|
-
return storageToken;
|
|
284
|
-
},
|
|
285
|
-
);
|
|
286
|
-
};
|
|
287
|
-
|
|
288
272
|
const getAuthorizationHeader: AuthorizationHeaderGetter = (
|
|
289
273
|
token: ITokenResponse,
|
|
290
274
|
): string => {
|
|
@@ -298,10 +282,11 @@ export class RouterliciousStorageRestWrapper extends RouterliciousRestWrapper {
|
|
|
298
282
|
const restWrapper = new RouterliciousStorageRestWrapper(
|
|
299
283
|
logger,
|
|
300
284
|
rateLimiter,
|
|
301
|
-
|
|
285
|
+
tokenFetcher,
|
|
302
286
|
getAuthorizationHeader,
|
|
303
287
|
useRestLess,
|
|
304
288
|
baseurl,
|
|
289
|
+
initialTokenP,
|
|
305
290
|
defaultQueryString,
|
|
306
291
|
);
|
|
307
292
|
|
|
@@ -317,6 +302,7 @@ export class RouterliciousOrdererRestWrapper extends RouterliciousRestWrapper {
|
|
|
317
302
|
getAuthorizationHeader: AuthorizationHeaderGetter,
|
|
318
303
|
useRestLess: boolean,
|
|
319
304
|
baseurl?: string,
|
|
305
|
+
initialTokenP?: Promise<ITokenResponse>,
|
|
320
306
|
defaultQueryString: QueryStringType = {},
|
|
321
307
|
) {
|
|
322
308
|
super(
|
|
@@ -326,18 +312,18 @@ export class RouterliciousOrdererRestWrapper extends RouterliciousRestWrapper {
|
|
|
326
312
|
getAuthorizationHeader,
|
|
327
313
|
useRestLess,
|
|
328
314
|
baseurl,
|
|
315
|
+
initialTokenP,
|
|
329
316
|
defaultQueryString,
|
|
330
317
|
);
|
|
331
318
|
}
|
|
332
319
|
|
|
333
320
|
public static async load(
|
|
334
|
-
|
|
335
|
-
documentId: string | undefined,
|
|
336
|
-
tokenProvider: ITokenProvider,
|
|
321
|
+
tokenFetcher: TokenFetcher,
|
|
337
322
|
logger: ITelemetryLogger,
|
|
338
323
|
rateLimiter: RateLimiter,
|
|
339
324
|
useRestLess: boolean,
|
|
340
325
|
baseurl?: string,
|
|
326
|
+
initialTokenP?: Promise<ITokenResponse>,
|
|
341
327
|
): Promise<RouterliciousOrdererRestWrapper> {
|
|
342
328
|
const getAuthorizationHeader: AuthorizationHeaderGetter = (
|
|
343
329
|
token: ITokenResponse,
|
|
@@ -345,34 +331,71 @@ export class RouterliciousOrdererRestWrapper extends RouterliciousRestWrapper {
|
|
|
345
331
|
return `Basic ${token.jwt}`;
|
|
346
332
|
};
|
|
347
333
|
|
|
348
|
-
const fetchOrdererToken = async (refreshToken?: boolean): Promise<ITokenResponse> => {
|
|
349
|
-
return PerformanceEvent.timedExecAsync(
|
|
350
|
-
logger,
|
|
351
|
-
{
|
|
352
|
-
eventName: "FetchOrdererToken",
|
|
353
|
-
docId: documentId,
|
|
354
|
-
},
|
|
355
|
-
async () => {
|
|
356
|
-
const ordererToken = await tokenProvider.fetchOrdererToken(
|
|
357
|
-
tenantId,
|
|
358
|
-
documentId,
|
|
359
|
-
refreshToken,
|
|
360
|
-
);
|
|
361
|
-
|
|
362
|
-
return ordererToken;
|
|
363
|
-
},
|
|
364
|
-
);
|
|
365
|
-
};
|
|
366
|
-
|
|
367
334
|
const restWrapper = new RouterliciousOrdererRestWrapper(
|
|
368
335
|
logger,
|
|
369
336
|
rateLimiter,
|
|
370
|
-
|
|
337
|
+
tokenFetcher,
|
|
371
338
|
getAuthorizationHeader,
|
|
372
339
|
useRestLess,
|
|
373
340
|
baseurl,
|
|
341
|
+
initialTokenP,
|
|
374
342
|
);
|
|
375
343
|
|
|
376
344
|
return restWrapper;
|
|
377
345
|
}
|
|
378
346
|
}
|
|
347
|
+
|
|
348
|
+
export function toInstrumentedR11sOrdererTokenFetcher(
|
|
349
|
+
tenantId: string,
|
|
350
|
+
documentId: string | undefined,
|
|
351
|
+
tokenProvider: ITokenProvider,
|
|
352
|
+
logger: ITelemetryLogger,
|
|
353
|
+
): TokenFetcher {
|
|
354
|
+
const fetchOrdererToken = async (refreshToken?: boolean): Promise<ITokenResponse> => {
|
|
355
|
+
return PerformanceEvent.timedExecAsync(
|
|
356
|
+
logger,
|
|
357
|
+
{
|
|
358
|
+
eventName: "FetchOrdererToken",
|
|
359
|
+
docId: documentId,
|
|
360
|
+
},
|
|
361
|
+
async () => {
|
|
362
|
+
const ordererToken = await tokenProvider.fetchOrdererToken(
|
|
363
|
+
tenantId,
|
|
364
|
+
documentId,
|
|
365
|
+
refreshToken,
|
|
366
|
+
);
|
|
367
|
+
|
|
368
|
+
return ordererToken;
|
|
369
|
+
},
|
|
370
|
+
);
|
|
371
|
+
};
|
|
372
|
+
return fetchOrdererToken;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
export function toInstrumentedR11sStorageTokenFetcher(
|
|
376
|
+
tenantId: string,
|
|
377
|
+
documentId: string,
|
|
378
|
+
tokenProvider: ITokenProvider,
|
|
379
|
+
logger: ITelemetryLogger,
|
|
380
|
+
): TokenFetcher {
|
|
381
|
+
const fetchStorageToken = async (refreshToken?: boolean): Promise<ITokenResponse> => {
|
|
382
|
+
return PerformanceEvent.timedExecAsync(
|
|
383
|
+
logger,
|
|
384
|
+
{
|
|
385
|
+
eventName: "FetchStorageToken",
|
|
386
|
+
docId: documentId,
|
|
387
|
+
},
|
|
388
|
+
async () => {
|
|
389
|
+
// Craft credentials using tenant id and token
|
|
390
|
+
const storageToken = await tokenProvider.fetchStorageToken(
|
|
391
|
+
tenantId,
|
|
392
|
+
documentId,
|
|
393
|
+
refreshToken,
|
|
394
|
+
);
|
|
395
|
+
|
|
396
|
+
return storageToken;
|
|
397
|
+
},
|
|
398
|
+
);
|
|
399
|
+
};
|
|
400
|
+
return fetchStorageToken;
|
|
401
|
+
}
|