@typespec/ts-http-runtime 1.0.0-alpha.20240110.1 → 1.0.0-alpha.20240117.1

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/index.js CHANGED
@@ -4,11 +4,11 @@ Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var os = require('os');
6
6
  var util = require('util');
7
- var httpsProxyAgent = require('https-proxy-agent');
8
- var httpProxyAgent = require('http-proxy-agent');
9
7
  var tslib = require('tslib');
10
8
  var stream = require('stream');
11
9
  var crypto = require('crypto');
10
+ var httpsProxyAgent = require('https-proxy-agent');
11
+ var httpProxyAgent = require('http-proxy-agent');
12
12
  var http = require('http');
13
13
  var https = require('https');
14
14
  var zlib = require('zlib');
@@ -804,282 +804,592 @@ function userAgentPolicy(options = {}) {
804
804
  // Copyright (c) Microsoft Corporation.
805
805
  // Licensed under the MIT license.
806
806
  /**
807
- * The programmatic identifier of the decompressResponsePolicy.
807
+ * The helper that transforms bytes with specific character encoding into string
808
+ * @param bytes - the uint8array bytes
809
+ * @param format - the format we use to encode the byte
810
+ * @returns a string of the encoded string
808
811
  */
809
- const decompressResponsePolicyName = "decompressResponsePolicy";
812
+ function uint8ArrayToString(bytes, format) {
813
+ return Buffer.from(bytes).toString(format);
814
+ }
810
815
  /**
811
- * A policy to enable response decompression according to Accept-Encoding header
812
- * https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Encoding
816
+ * The helper that transforms string to specific character encoded bytes array.
817
+ * @param value - the string to be converted
818
+ * @param format - the format we use to decode the value
819
+ * @returns a uint8array
813
820
  */
814
- function decompressResponsePolicy() {
815
- return {
816
- name: decompressResponsePolicyName,
817
- async sendRequest(request, next) {
818
- // HEAD requests have no body
819
- if (request.method !== "HEAD") {
820
- request.headers.set("Accept-Encoding", "gzip,deflate");
821
- }
822
- return next(request);
823
- },
824
- };
821
+ function stringToUint8Array(value, format) {
822
+ return Buffer.from(value, format);
825
823
  }
826
824
 
827
825
  // Copyright (c) Microsoft Corporation.
828
826
  // Licensed under the MIT license.
829
827
  /**
830
- * Returns a random integer value between a lower and upper bound,
831
- * inclusive of both bounds.
832
- * Note that this uses Math.random and isn't secure. If you need to use
833
- * this for any kind of security purpose, find a better source of random.
834
- * @param min - The smallest integer value allowed.
835
- * @param max - The largest integer value allowed.
828
+ * Helper TypeGuard that checks if something is defined or not.
829
+ * @param thing - Anything
836
830
  */
837
- function getRandomIntegerInclusive(min, max) {
838
- // Make sure inputs are integers.
839
- min = Math.ceil(min);
840
- max = Math.floor(max);
841
- // Pick a random offset from zero to the size of the range.
842
- // Since Math.random() can never return 1, we have to make the range one larger
843
- // in order to be inclusive of the maximum value after we take the floor.
844
- const offset = Math.floor(Math.random() * (max - min + 1));
845
- return offset + min;
831
+ function isDefined(thing) {
832
+ return typeof thing !== "undefined" && thing !== null;
846
833
  }
847
-
848
- // Copyright (c) Microsoft Corporation.
849
- // Licensed under the MIT license.
850
834
  /**
851
- * This error is thrown when an asynchronous operation has been aborted.
852
- * Check for this error by testing the `name` that the name property of the
853
- * error matches `"AbortError"`.
854
- *
855
- * @example
856
- * ```ts
857
- * const controller = new AbortController();
858
- * controller.abort();
859
- * try {
860
- * doAsyncWork(controller.signal)
861
- * } catch (e) {
862
- * if (e.name === 'AbortError') {
863
- * // handle abort error here.
864
- * }
865
- * }
866
- * ```
835
+ * Helper TypeGuard that checks if the input is an object with the specified properties.
836
+ * @param thing - Anything.
837
+ * @param properties - The name of the properties that should appear in the object.
867
838
  */
868
- class AbortError extends Error {
869
- constructor(message) {
870
- super(message);
871
- this.name = "AbortError";
839
+ function isObjectWithProperties(thing, properties) {
840
+ if (!isDefined(thing) || typeof thing !== "object") {
841
+ return false;
872
842
  }
843
+ for (const property of properties) {
844
+ if (!objectHasProperty(thing, property)) {
845
+ return false;
846
+ }
847
+ }
848
+ return true;
849
+ }
850
+ /**
851
+ * Helper TypeGuard that checks if the input is an object with the specified property.
852
+ * @param thing - Any object.
853
+ * @param property - The name of the property that should appear in the object.
854
+ */
855
+ function objectHasProperty(thing, property) {
856
+ return (isDefined(thing) && typeof thing === "object" && property in thing);
857
+ }
858
+ function isNodeReadableStream(x) {
859
+ return Boolean(x && typeof x["pipe"] === "function");
860
+ }
861
+ function isWebReadableStream(x) {
862
+ return Boolean(x &&
863
+ typeof x.getReader === "function" &&
864
+ typeof x.tee === "function");
865
+ }
866
+ function isReadableStream$1(x) {
867
+ return isNodeReadableStream(x) || isWebReadableStream(x);
868
+ }
869
+ function isBlob(x) {
870
+ return typeof x.stream === "function";
873
871
  }
874
872
 
875
873
  // Copyright (c) Microsoft Corporation.
876
874
  // Licensed under the MIT license.
877
- const StandardAbortMessage$1 = "The operation was aborted.";
878
- /**
879
- * A wrapper for setTimeout that resolves a promise after delayInMs milliseconds.
880
- * @param delayInMs - The number of milliseconds to be delayed.
881
- * @param value - The value to be resolved with after a timeout of t milliseconds.
882
- * @param options - The options for delay - currently abort options
883
- * - abortSignal - The abortSignal associated with containing operation.
884
- * - abortErrorMsg - The abort error message associated with containing operation.
885
- * @returns Resolved promise
886
- */
887
- function delay$1(delayInMs, value, options) {
888
- return new Promise((resolve, reject) => {
889
- let timer = undefined;
890
- let onAborted = undefined;
891
- const rejectOnAbort = () => {
892
- return reject(new AbortError((options === null || options === void 0 ? void 0 : options.abortErrorMsg) ? options === null || options === void 0 ? void 0 : options.abortErrorMsg : StandardAbortMessage$1));
893
- };
894
- const removeListeners = () => {
895
- if ((options === null || options === void 0 ? void 0 : options.abortSignal) && onAborted) {
896
- options.abortSignal.removeEventListener("abort", onAborted);
897
- }
898
- };
899
- onAborted = () => {
900
- if (timer) {
901
- clearTimeout(timer);
875
+ function streamAsyncIterator() {
876
+ return tslib.__asyncGenerator(this, arguments, function* streamAsyncIterator_1() {
877
+ const reader = this.getReader();
878
+ try {
879
+ while (true) {
880
+ const { done, value } = yield tslib.__await(reader.read());
881
+ if (done) {
882
+ return yield tslib.__await(void 0);
883
+ }
884
+ yield yield tslib.__await(value);
902
885
  }
903
- removeListeners();
904
- return rejectOnAbort();
905
- };
906
- if ((options === null || options === void 0 ? void 0 : options.abortSignal) && options.abortSignal.aborted) {
907
- return rejectOnAbort();
908
886
  }
909
- timer = setTimeout(() => {
910
- removeListeners();
911
- resolve(value);
912
- }, delayInMs);
913
- if (options === null || options === void 0 ? void 0 : options.abortSignal) {
914
- options.abortSignal.addEventListener("abort", onAborted);
887
+ finally {
888
+ reader.releaseLock();
915
889
  }
916
890
  });
917
891
  }
918
- /**
919
- * @internal
920
- * @returns the parsed value or undefined if the parsed value is invalid.
921
- */
922
- function parseHeaderValueAsNumber(response, headerName) {
923
- const value = response.headers.get(headerName);
924
- if (!value)
925
- return;
926
- const valueAsNum = Number(value);
927
- if (Number.isNaN(valueAsNum))
928
- return;
929
- return valueAsNum;
892
+ function makeAsyncIterable(webStream) {
893
+ if (!webStream[Symbol.asyncIterator]) {
894
+ webStream[Symbol.asyncIterator] = streamAsyncIterator.bind(webStream);
895
+ }
896
+ if (!webStream.values) {
897
+ webStream.values = streamAsyncIterator.bind(webStream);
898
+ }
899
+ }
900
+ function nodeStreamFromWebStream(webStream) {
901
+ makeAsyncIterable(webStream);
902
+ return stream.Readable.fromWeb(webStream);
903
+ }
904
+ function toWebStream(stream$1) {
905
+ return isWebReadableStream(stream$1)
906
+ ? stream$1
907
+ : stream.Readable.toWeb(stream.Readable.from(stream$1));
908
+ }
909
+ function toStream(source) {
910
+ if (source instanceof Uint8Array) {
911
+ return stream.Readable.from(Buffer.from(source));
912
+ }
913
+ else if (isBlob(source)) {
914
+ return nodeStreamFromWebStream(source.stream());
915
+ }
916
+ else if (isNodeReadableStream(source)) {
917
+ return source;
918
+ }
919
+ else {
920
+ return nodeStreamFromWebStream(source);
921
+ }
922
+ }
923
+ function concatenateStreams(sources) {
924
+ if (sources.some(isWebReadableStream)) {
925
+ throw new Error("Was not expecting a Web stream here");
926
+ }
927
+ return stream.Readable.from((function () {
928
+ return tslib.__asyncGenerator(this, arguments, function* () {
929
+ var _a, e_1, _b, _c;
930
+ for (const stream of sources) {
931
+ try {
932
+ for (var _d = true, stream_1 = (e_1 = void 0, tslib.__asyncValues(stream)), stream_1_1; stream_1_1 = yield tslib.__await(stream_1.next()), _a = stream_1_1.done, !_a; _d = true) {
933
+ _c = stream_1_1.value;
934
+ _d = false;
935
+ const chunk = _c;
936
+ yield yield tslib.__await(chunk);
937
+ }
938
+ }
939
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
940
+ finally {
941
+ try {
942
+ if (!_d && !_a && (_b = stream_1.return)) yield tslib.__await(_b.call(stream_1));
943
+ }
944
+ finally { if (e_1) throw e_1.error; }
945
+ }
946
+ }
947
+ });
948
+ })());
930
949
  }
931
950
 
932
951
  // Copyright (c) Microsoft Corporation.
933
952
  // Licensed under the MIT license.
934
- /**
935
- * The header that comes back from services representing
936
- * the amount of time (minimum) to wait to retry (in seconds or timestamp after which we can retry).
937
- */
938
- const RetryAfterHeader = "Retry-After";
939
- /**
940
- * The headers that come back from services representing
941
- * the amount of time (minimum) to wait to retry.
942
- *
943
- * "retry-after-ms", "x-ms-retry-after-ms" : milliseconds
944
- * "Retry-After" : seconds or timestamp
953
+ /*
954
+ * NOTE: When moving this file, please update "react-native" section in package.json.
945
955
  */
946
- const AllRetryAfterHeaders = ["retry-after-ms", "x-ms-retry-after-ms", RetryAfterHeader];
947
956
  /**
948
- * A response is a throttling retry response if it has a throttling status code (429 or 503),
949
- * as long as one of the [ "Retry-After" or "retry-after-ms" or "x-ms-retry-after-ms" ] headers has a valid value.
950
- *
951
- * Returns the `retryAfterInMs` value if the response is a throttling retry response.
952
- * If not throttling retry response, returns `undefined`.
957
+ * Generated Universally Unique Identifier
953
958
  *
954
- * @internal
959
+ * @returns RFC4122 v4 UUID.
955
960
  */
956
- function getRetryAfterInMs(response) {
957
- if (!(response && [429, 503].includes(response.status)))
958
- return undefined;
959
- try {
960
- // Headers: "retry-after-ms", "x-ms-retry-after-ms", "Retry-After"
961
- for (const header of AllRetryAfterHeaders) {
962
- const retryAfterValue = parseHeaderValueAsNumber(response, header);
963
- if (retryAfterValue === 0 || retryAfterValue) {
964
- // "Retry-After" header ==> seconds
965
- // "retry-after-ms", "x-ms-retry-after-ms" headers ==> milli-seconds
966
- const multiplyingFactor = header === RetryAfterHeader ? 1000 : 1;
967
- return retryAfterValue * multiplyingFactor; // in milli-seconds
968
- }
961
+ function generateUUID() {
962
+ let uuid = "";
963
+ for (let i = 0; i < 32; i++) {
964
+ // Generate a random number between 0 and 15
965
+ const randomNumber = Math.floor(Math.random() * 16);
966
+ // Set the UUID version to 4 in the 13th position
967
+ if (i === 12) {
968
+ uuid += "4";
969
+ }
970
+ else if (i === 16) {
971
+ // Set the UUID variant to "10" in the 17th position
972
+ uuid += (randomNumber & 0x3) | 0x8;
973
+ }
974
+ else {
975
+ // Add a random hexadecimal digit to the UUID string
976
+ uuid += randomNumber.toString(16);
977
+ }
978
+ // Add hyphens to the UUID string at the appropriate positions
979
+ if (i === 7 || i === 11 || i === 15 || i === 19) {
980
+ uuid += "-";
969
981
  }
970
- // RetryAfterHeader ("Retry-After") has a special case where it might be formatted as a date instead of a number of seconds
971
- const retryAfterHeader = response.headers.get(RetryAfterHeader);
972
- if (!retryAfterHeader)
973
- return;
974
- const date = Date.parse(retryAfterHeader);
975
- const diff = date - Date.now();
976
- // negative diff would mean a date in the past, so retry asap with 0 milliseconds
977
- return Number.isFinite(diff) ? Math.max(0, diff) : undefined;
978
982
  }
979
- catch (e) {
983
+ return uuid;
984
+ }
985
+
986
+ // Copyright (c) Microsoft Corporation.
987
+ // Licensed under the MIT license.
988
+ var _a$1;
989
+ // NOTE: This is a workaround until we can use `globalThis.crypto.randomUUID` in Node.js 19+.
990
+ let uuidFunction = typeof ((_a$1 = globalThis === null || globalThis === void 0 ? void 0 : globalThis.crypto) === null || _a$1 === void 0 ? void 0 : _a$1.randomUUID) === "function"
991
+ ? globalThis.crypto.randomUUID.bind(globalThis.crypto)
992
+ : crypto.randomUUID;
993
+ // Not defined in earlier versions of Node.js 14
994
+ if (!uuidFunction) {
995
+ uuidFunction = generateUUID;
996
+ }
997
+ /**
998
+ * Generated Universally Unique Identifier
999
+ *
1000
+ * @returns RFC4122 v4 UUID.
1001
+ */
1002
+ function randomUUID() {
1003
+ return uuidFunction();
1004
+ }
1005
+
1006
+ // Copyright (c) Microsoft Corporation.
1007
+ // Licensed under the MIT license.
1008
+ function generateBoundary() {
1009
+ return `----AzSDKFormBoundary${randomUUID()}`;
1010
+ }
1011
+ function encodeHeaders(headers) {
1012
+ let result = "";
1013
+ for (const [key, value] of headers) {
1014
+ result += `${key}: ${value}\r\n`;
1015
+ }
1016
+ return result;
1017
+ }
1018
+ function getLength(source) {
1019
+ if (source instanceof Uint8Array) {
1020
+ return source.byteLength;
1021
+ }
1022
+ else if (isBlob(source)) {
1023
+ // if was created using createFile then -1 means we have an unknown size
1024
+ return source.size === -1 ? undefined : source.size;
1025
+ }
1026
+ else {
980
1027
  return undefined;
981
1028
  }
982
1029
  }
1030
+ function getTotalLength(sources) {
1031
+ let total = 0;
1032
+ for (const source of sources) {
1033
+ const partLength = getLength(source);
1034
+ if (partLength === undefined) {
1035
+ return undefined;
1036
+ }
1037
+ else {
1038
+ total += partLength;
1039
+ }
1040
+ }
1041
+ return total;
1042
+ }
1043
+ function buildRequestBody(request, parts, boundary) {
1044
+ const sources = [
1045
+ stringToUint8Array(`--${boundary}`, "utf-8"),
1046
+ ...parts.flatMap((part) => [
1047
+ stringToUint8Array("\r\n", "utf-8"),
1048
+ stringToUint8Array(encodeHeaders(part.headers), "utf-8"),
1049
+ stringToUint8Array("\r\n", "utf-8"),
1050
+ part.body,
1051
+ stringToUint8Array(`\r\n--${boundary}`, "utf-8"),
1052
+ ]),
1053
+ stringToUint8Array("--\r\n\r\n", "utf-8"),
1054
+ ];
1055
+ const contentLength = getTotalLength(sources);
1056
+ if (contentLength) {
1057
+ request.headers.set("Content-Length", contentLength);
1058
+ }
1059
+ request.body = (() => concatenateStreams(sources.map((source) => (typeof source === "function" ? source() : source)).map(toStream)));
1060
+ }
983
1061
  /**
984
- * A response is a retry response if it has a throttling status code (429 or 503),
985
- * as long as one of the [ "Retry-After" or "retry-after-ms" or "x-ms-retry-after-ms" ] headers has a valid value.
1062
+ * Name of multipart policy
986
1063
  */
987
- function isThrottlingRetryResponse(response) {
988
- return Number.isFinite(getRetryAfterInMs(response));
1064
+ const multipartPolicyName = "multipartPolicy";
1065
+ const maxBoundaryLength = 70;
1066
+ const validBoundaryCharacters = new Set(`abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'()+,-./:=?`);
1067
+ function assertValidBoundary(boundary) {
1068
+ if (boundary.length > maxBoundaryLength) {
1069
+ throw new Error(`Multipart boundary "${boundary}" exceeds maximum length of 70 characters`);
1070
+ }
1071
+ if (Array.from(boundary).some((x) => !validBoundaryCharacters.has(x))) {
1072
+ throw new Error(`Multipart boundary "${boundary}" contains invalid characters`);
1073
+ }
989
1074
  }
990
- function throttlingRetryStrategy() {
1075
+ /**
1076
+ * Pipeline policy for multipart requests
1077
+ */
1078
+ function multipartPolicy() {
991
1079
  return {
992
- name: "throttlingRetryStrategy",
993
- retry({ response }) {
994
- const retryAfterInMs = getRetryAfterInMs(response);
995
- if (!Number.isFinite(retryAfterInMs)) {
996
- return { skipStrategy: true };
1080
+ name: multipartPolicyName,
1081
+ sendRequest(request, next) {
1082
+ var _a;
1083
+ if (!request.multipartBody) {
1084
+ return next(request);
997
1085
  }
998
- return {
999
- retryAfterInMs,
1000
- };
1086
+ if (request.body) {
1087
+ throw new Error("multipartBody and regular body cannot be set at the same time");
1088
+ }
1089
+ let boundary = request.multipartBody.boundary;
1090
+ const contentTypeHeader = (_a = request.headers.get("Content-Type")) !== null && _a !== void 0 ? _a : "multipart/mixed";
1091
+ const parsedHeader = contentTypeHeader.match(/^(multipart\/[^ ;]+)(?:; *boundary=(.+))?$/);
1092
+ if (!parsedHeader) {
1093
+ throw new Error(`Got multipart request body, but content-type header was not multipart: ${contentTypeHeader}`);
1094
+ }
1095
+ const [, contentType, parsedBoundary] = parsedHeader;
1096
+ if (parsedBoundary && boundary && parsedBoundary !== boundary) {
1097
+ throw new Error(`Multipart boundary was specified as ${parsedBoundary} in the header, but got ${boundary} in the request body`);
1098
+ }
1099
+ boundary !== null && boundary !== void 0 ? boundary : (boundary = parsedBoundary);
1100
+ if (boundary) {
1101
+ assertValidBoundary(boundary);
1102
+ }
1103
+ else {
1104
+ boundary = generateBoundary();
1105
+ }
1106
+ request.headers.set("Content-Type", `${contentType}; boundary=${boundary}`);
1107
+ buildRequestBody(request, request.multipartBody.parts, boundary);
1108
+ request.multipartBody = undefined;
1109
+ return next(request);
1001
1110
  },
1002
1111
  };
1003
1112
  }
1004
1113
 
1005
1114
  // Copyright (c) Microsoft Corporation.
1006
1115
  // Licensed under the MIT license.
1007
- // intervals are in milliseconds
1008
- const DEFAULT_CLIENT_RETRY_INTERVAL = 1000;
1009
- const DEFAULT_CLIENT_MAX_RETRY_INTERVAL = 1000 * 64;
1010
1116
  /**
1011
- * A retry strategy that retries with an exponentially increasing delay in these two cases:
1012
- * - When there are errors in the underlying transport layer (e.g. DNS lookup failures).
1013
- * - Or otherwise if the outgoing request fails (408, greater or equal than 500, except for 501 and 505).
1117
+ * The programmatic identifier of the decompressResponsePolicy.
1014
1118
  */
1015
- function exponentialRetryStrategy(options = {}) {
1016
- var _a, _b;
1017
- const retryInterval = (_a = options.retryDelayInMs) !== null && _a !== void 0 ? _a : DEFAULT_CLIENT_RETRY_INTERVAL;
1018
- const maxRetryInterval = (_b = options.maxRetryDelayInMs) !== null && _b !== void 0 ? _b : DEFAULT_CLIENT_MAX_RETRY_INTERVAL;
1019
- let retryAfterInMs = retryInterval;
1119
+ const decompressResponsePolicyName = "decompressResponsePolicy";
1120
+ /**
1121
+ * A policy to enable response decompression according to Accept-Encoding header
1122
+ * https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Encoding
1123
+ */
1124
+ function decompressResponsePolicy() {
1020
1125
  return {
1021
- name: "exponentialRetryStrategy",
1022
- retry({ retryCount, response, responseError }) {
1023
- const matchedSystemError = isSystemError(responseError);
1024
- const ignoreSystemErrors = matchedSystemError && options.ignoreSystemErrors;
1025
- const isExponential = isExponentialRetryResponse(response);
1026
- const ignoreExponentialResponse = isExponential && options.ignoreHttpStatusCodes;
1027
- const unknownResponse = response && (isThrottlingRetryResponse(response) || !isExponential);
1028
- if (unknownResponse || ignoreExponentialResponse || ignoreSystemErrors) {
1029
- return { skipStrategy: true };
1030
- }
1031
- if (responseError && !matchedSystemError && !isExponential) {
1032
- return { errorToThrow: responseError };
1126
+ name: decompressResponsePolicyName,
1127
+ async sendRequest(request, next) {
1128
+ // HEAD requests have no body
1129
+ if (request.method !== "HEAD") {
1130
+ request.headers.set("Accept-Encoding", "gzip,deflate");
1033
1131
  }
1034
- // Exponentially increase the delay each time
1035
- const exponentialDelay = retryAfterInMs * Math.pow(2, retryCount);
1036
- // Don't let the delay exceed the maximum
1037
- const clampedExponentialDelay = Math.min(maxRetryInterval, exponentialDelay);
1038
- // Allow the final value to have some "jitter" (within 50% of the delay size) so
1039
- // that retries across multiple clients don't occur simultaneously.
1040
- retryAfterInMs =
1041
- clampedExponentialDelay / 2 + getRandomIntegerInclusive(0, clampedExponentialDelay / 2);
1042
- return { retryAfterInMs };
1132
+ return next(request);
1043
1133
  },
1044
1134
  };
1045
1135
  }
1136
+
1137
+ // Copyright (c) Microsoft Corporation.
1138
+ // Licensed under the MIT license.
1046
1139
  /**
1047
- * A response is a retry response if it has status codes:
1048
- * - 408, or
1049
- * - Greater or equal than 500, except for 501 and 505.
1050
- */
1051
- function isExponentialRetryResponse(response) {
1052
- return Boolean(response &&
1053
- response.status !== undefined &&
1054
- (response.status >= 500 || response.status === 408) &&
1055
- response.status !== 501 &&
1056
- response.status !== 505);
1057
- }
1058
- /**
1059
- * Determines whether an error from a pipeline response was triggered in the network layer.
1140
+ * Returns a random integer value between a lower and upper bound,
1141
+ * inclusive of both bounds.
1142
+ * Note that this uses Math.random and isn't secure. If you need to use
1143
+ * this for any kind of security purpose, find a better source of random.
1144
+ * @param min - The smallest integer value allowed.
1145
+ * @param max - The largest integer value allowed.
1060
1146
  */
1061
- function isSystemError(err) {
1062
- if (!err) {
1063
- return false;
1064
- }
1065
- return (err.code === "ETIMEDOUT" ||
1066
- err.code === "ESOCKETTIMEDOUT" ||
1067
- err.code === "ECONNREFUSED" ||
1068
- err.code === "ECONNRESET" ||
1069
- err.code === "ENOENT" ||
1070
- err.code === "ENOTFOUND");
1147
+ function getRandomIntegerInclusive(min, max) {
1148
+ // Make sure inputs are integers.
1149
+ min = Math.ceil(min);
1150
+ max = Math.floor(max);
1151
+ // Pick a random offset from zero to the size of the range.
1152
+ // Since Math.random() can never return 1, we have to make the range one larger
1153
+ // in order to be inclusive of the maximum value after we take the floor.
1154
+ const offset = Math.floor(Math.random() * (max - min + 1));
1155
+ return offset + min;
1071
1156
  }
1072
1157
 
1073
1158
  // Copyright (c) Microsoft Corporation.
1074
1159
  // Licensed under the MIT license.
1075
- const retryPolicyLogger = createClientLogger("core-rest-pipeline retryPolicy");
1076
- /**
1077
- * The programmatic identifier of the retryPolicy.
1078
- */
1079
- const retryPolicyName = "retryPolicy";
1080
1160
  /**
1081
- * retryPolicy is a generic policy to enable retrying requests when certain conditions are met
1082
- */
1161
+ * This error is thrown when an asynchronous operation has been aborted.
1162
+ * Check for this error by testing the `name` that the name property of the
1163
+ * error matches `"AbortError"`.
1164
+ *
1165
+ * @example
1166
+ * ```ts
1167
+ * const controller = new AbortController();
1168
+ * controller.abort();
1169
+ * try {
1170
+ * doAsyncWork(controller.signal)
1171
+ * } catch (e) {
1172
+ * if (e.name === 'AbortError') {
1173
+ * // handle abort error here.
1174
+ * }
1175
+ * }
1176
+ * ```
1177
+ */
1178
+ class AbortError extends Error {
1179
+ constructor(message) {
1180
+ super(message);
1181
+ this.name = "AbortError";
1182
+ }
1183
+ }
1184
+
1185
+ // Copyright (c) Microsoft Corporation.
1186
+ // Licensed under the MIT license.
1187
+ const StandardAbortMessage$1 = "The operation was aborted.";
1188
+ /**
1189
+ * A wrapper for setTimeout that resolves a promise after delayInMs milliseconds.
1190
+ * @param delayInMs - The number of milliseconds to be delayed.
1191
+ * @param value - The value to be resolved with after a timeout of t milliseconds.
1192
+ * @param options - The options for delay - currently abort options
1193
+ * - abortSignal - The abortSignal associated with containing operation.
1194
+ * - abortErrorMsg - The abort error message associated with containing operation.
1195
+ * @returns Resolved promise
1196
+ */
1197
+ function delay$1(delayInMs, value, options) {
1198
+ return new Promise((resolve, reject) => {
1199
+ let timer = undefined;
1200
+ let onAborted = undefined;
1201
+ const rejectOnAbort = () => {
1202
+ return reject(new AbortError((options === null || options === void 0 ? void 0 : options.abortErrorMsg) ? options === null || options === void 0 ? void 0 : options.abortErrorMsg : StandardAbortMessage$1));
1203
+ };
1204
+ const removeListeners = () => {
1205
+ if ((options === null || options === void 0 ? void 0 : options.abortSignal) && onAborted) {
1206
+ options.abortSignal.removeEventListener("abort", onAborted);
1207
+ }
1208
+ };
1209
+ onAborted = () => {
1210
+ if (timer) {
1211
+ clearTimeout(timer);
1212
+ }
1213
+ removeListeners();
1214
+ return rejectOnAbort();
1215
+ };
1216
+ if ((options === null || options === void 0 ? void 0 : options.abortSignal) && options.abortSignal.aborted) {
1217
+ return rejectOnAbort();
1218
+ }
1219
+ timer = setTimeout(() => {
1220
+ removeListeners();
1221
+ resolve(value);
1222
+ }, delayInMs);
1223
+ if (options === null || options === void 0 ? void 0 : options.abortSignal) {
1224
+ options.abortSignal.addEventListener("abort", onAborted);
1225
+ }
1226
+ });
1227
+ }
1228
+ /**
1229
+ * @internal
1230
+ * @returns the parsed value or undefined if the parsed value is invalid.
1231
+ */
1232
+ function parseHeaderValueAsNumber(response, headerName) {
1233
+ const value = response.headers.get(headerName);
1234
+ if (!value)
1235
+ return;
1236
+ const valueAsNum = Number(value);
1237
+ if (Number.isNaN(valueAsNum))
1238
+ return;
1239
+ return valueAsNum;
1240
+ }
1241
+
1242
+ // Copyright (c) Microsoft Corporation.
1243
+ // Licensed under the MIT license.
1244
+ /**
1245
+ * The header that comes back from services representing
1246
+ * the amount of time (minimum) to wait to retry (in seconds or timestamp after which we can retry).
1247
+ */
1248
+ const RetryAfterHeader = "Retry-After";
1249
+ /**
1250
+ * The headers that come back from services representing
1251
+ * the amount of time (minimum) to wait to retry.
1252
+ *
1253
+ * "retry-after-ms", "x-ms-retry-after-ms" : milliseconds
1254
+ * "Retry-After" : seconds or timestamp
1255
+ */
1256
+ const AllRetryAfterHeaders = ["retry-after-ms", "x-ms-retry-after-ms", RetryAfterHeader];
1257
+ /**
1258
+ * A response is a throttling retry response if it has a throttling status code (429 or 503),
1259
+ * as long as one of the [ "Retry-After" or "retry-after-ms" or "x-ms-retry-after-ms" ] headers has a valid value.
1260
+ *
1261
+ * Returns the `retryAfterInMs` value if the response is a throttling retry response.
1262
+ * If not throttling retry response, returns `undefined`.
1263
+ *
1264
+ * @internal
1265
+ */
1266
+ function getRetryAfterInMs(response) {
1267
+ if (!(response && [429, 503].includes(response.status)))
1268
+ return undefined;
1269
+ try {
1270
+ // Headers: "retry-after-ms", "x-ms-retry-after-ms", "Retry-After"
1271
+ for (const header of AllRetryAfterHeaders) {
1272
+ const retryAfterValue = parseHeaderValueAsNumber(response, header);
1273
+ if (retryAfterValue === 0 || retryAfterValue) {
1274
+ // "Retry-After" header ==> seconds
1275
+ // "retry-after-ms", "x-ms-retry-after-ms" headers ==> milli-seconds
1276
+ const multiplyingFactor = header === RetryAfterHeader ? 1000 : 1;
1277
+ return retryAfterValue * multiplyingFactor; // in milli-seconds
1278
+ }
1279
+ }
1280
+ // RetryAfterHeader ("Retry-After") has a special case where it might be formatted as a date instead of a number of seconds
1281
+ const retryAfterHeader = response.headers.get(RetryAfterHeader);
1282
+ if (!retryAfterHeader)
1283
+ return;
1284
+ const date = Date.parse(retryAfterHeader);
1285
+ const diff = date - Date.now();
1286
+ // negative diff would mean a date in the past, so retry asap with 0 milliseconds
1287
+ return Number.isFinite(diff) ? Math.max(0, diff) : undefined;
1288
+ }
1289
+ catch (e) {
1290
+ return undefined;
1291
+ }
1292
+ }
1293
+ /**
1294
+ * A response is a retry response if it has a throttling status code (429 or 503),
1295
+ * as long as one of the [ "Retry-After" or "retry-after-ms" or "x-ms-retry-after-ms" ] headers has a valid value.
1296
+ */
1297
+ function isThrottlingRetryResponse(response) {
1298
+ return Number.isFinite(getRetryAfterInMs(response));
1299
+ }
1300
+ function throttlingRetryStrategy() {
1301
+ return {
1302
+ name: "throttlingRetryStrategy",
1303
+ retry({ response }) {
1304
+ const retryAfterInMs = getRetryAfterInMs(response);
1305
+ if (!Number.isFinite(retryAfterInMs)) {
1306
+ return { skipStrategy: true };
1307
+ }
1308
+ return {
1309
+ retryAfterInMs,
1310
+ };
1311
+ },
1312
+ };
1313
+ }
1314
+
1315
+ // Copyright (c) Microsoft Corporation.
1316
+ // Licensed under the MIT license.
1317
+ // intervals are in milliseconds
1318
+ const DEFAULT_CLIENT_RETRY_INTERVAL = 1000;
1319
+ const DEFAULT_CLIENT_MAX_RETRY_INTERVAL = 1000 * 64;
1320
+ /**
1321
+ * A retry strategy that retries with an exponentially increasing delay in these two cases:
1322
+ * - When there are errors in the underlying transport layer (e.g. DNS lookup failures).
1323
+ * - Or otherwise if the outgoing request fails (408, greater or equal than 500, except for 501 and 505).
1324
+ */
1325
+ function exponentialRetryStrategy(options = {}) {
1326
+ var _a, _b;
1327
+ const retryInterval = (_a = options.retryDelayInMs) !== null && _a !== void 0 ? _a : DEFAULT_CLIENT_RETRY_INTERVAL;
1328
+ const maxRetryInterval = (_b = options.maxRetryDelayInMs) !== null && _b !== void 0 ? _b : DEFAULT_CLIENT_MAX_RETRY_INTERVAL;
1329
+ let retryAfterInMs = retryInterval;
1330
+ return {
1331
+ name: "exponentialRetryStrategy",
1332
+ retry({ retryCount, response, responseError }) {
1333
+ const matchedSystemError = isSystemError(responseError);
1334
+ const ignoreSystemErrors = matchedSystemError && options.ignoreSystemErrors;
1335
+ const isExponential = isExponentialRetryResponse(response);
1336
+ const ignoreExponentialResponse = isExponential && options.ignoreHttpStatusCodes;
1337
+ const unknownResponse = response && (isThrottlingRetryResponse(response) || !isExponential);
1338
+ if (unknownResponse || ignoreExponentialResponse || ignoreSystemErrors) {
1339
+ return { skipStrategy: true };
1340
+ }
1341
+ if (responseError && !matchedSystemError && !isExponential) {
1342
+ return { errorToThrow: responseError };
1343
+ }
1344
+ // Exponentially increase the delay each time
1345
+ const exponentialDelay = retryAfterInMs * Math.pow(2, retryCount);
1346
+ // Don't let the delay exceed the maximum
1347
+ const clampedExponentialDelay = Math.min(maxRetryInterval, exponentialDelay);
1348
+ // Allow the final value to have some "jitter" (within 50% of the delay size) so
1349
+ // that retries across multiple clients don't occur simultaneously.
1350
+ retryAfterInMs =
1351
+ clampedExponentialDelay / 2 + getRandomIntegerInclusive(0, clampedExponentialDelay / 2);
1352
+ return { retryAfterInMs };
1353
+ },
1354
+ };
1355
+ }
1356
+ /**
1357
+ * A response is a retry response if it has status codes:
1358
+ * - 408, or
1359
+ * - Greater or equal than 500, except for 501 and 505.
1360
+ */
1361
+ function isExponentialRetryResponse(response) {
1362
+ return Boolean(response &&
1363
+ response.status !== undefined &&
1364
+ (response.status >= 500 || response.status === 408) &&
1365
+ response.status !== 501 &&
1366
+ response.status !== 505);
1367
+ }
1368
+ /**
1369
+ * Determines whether an error from a pipeline response was triggered in the network layer.
1370
+ */
1371
+ function isSystemError(err) {
1372
+ if (!err) {
1373
+ return false;
1374
+ }
1375
+ return (err.code === "ETIMEDOUT" ||
1376
+ err.code === "ESOCKETTIMEDOUT" ||
1377
+ err.code === "ECONNREFUSED" ||
1378
+ err.code === "ECONNRESET" ||
1379
+ err.code === "ENOENT" ||
1380
+ err.code === "ENOTFOUND");
1381
+ }
1382
+
1383
+ // Copyright (c) Microsoft Corporation.
1384
+ // Licensed under the MIT license.
1385
+ const retryPolicyLogger = createClientLogger("core-rest-pipeline retryPolicy");
1386
+ /**
1387
+ * The programmatic identifier of the retryPolicy.
1388
+ */
1389
+ const retryPolicyName = "retryPolicy";
1390
+ /**
1391
+ * retryPolicy is a generic policy to enable retrying requests when certain conditions are met
1392
+ */
1083
1393
  function retryPolicy(strategies, options = { maxRetries: DEFAULT_RETRY_POLICY_COUNT }) {
1084
1394
  const logger = options.logger || retryPolicyLogger;
1085
1395
  return {
@@ -1194,27 +1504,6 @@ function defaultRetryPolicy(options = {}) {
1194
1504
  };
1195
1505
  }
1196
1506
 
1197
- // Copyright (c) Microsoft Corporation.
1198
- // Licensed under the MIT license.
1199
- /**
1200
- * The helper that transforms bytes with specific character encoding into string
1201
- * @param bytes - the uint8array bytes
1202
- * @param format - the format we use to encode the byte
1203
- * @returns a string of the encoded string
1204
- */
1205
- function uint8ArrayToString(bytes, format) {
1206
- return Buffer.from(bytes).toString(format);
1207
- }
1208
- /**
1209
- * The helper that transforms string to specific character encoded bytes array.
1210
- * @param value - the string to be converted
1211
- * @param format - the format we use to decode the value
1212
- * @returns a uint8array
1213
- */
1214
- function stringToUint8Array(value, format) {
1215
- return Buffer.from(value, format);
1216
- }
1217
-
1218
1507
  // Copyright (c) Microsoft Corporation.
1219
1508
  // Licensed under the MIT license.
1220
1509
  function normalizeName(name) {
@@ -1379,13 +1668,13 @@ async function prepareFormData(formData, request) {
1379
1668
  });
1380
1669
  }
1381
1670
  }
1382
- request.multipartBody = { parts };
1383
1671
  }
1672
+ request.multipartBody = { parts };
1384
1673
  }
1385
1674
 
1386
1675
  // Copyright (c) Microsoft Corporation.
1387
1676
  // Licensed under the MIT license.
1388
- var _a$1, _b, _c, _d;
1677
+ var _a, _b, _c, _d;
1389
1678
  /**
1390
1679
  * A constant that indicates whether the environment the code is running is a Web Browser.
1391
1680
  */
@@ -1396,7 +1685,7 @@ const isBrowser = typeof window !== "undefined" && typeof window.document !== "u
1396
1685
  */
1397
1686
  const isWebWorker = typeof self === "object" &&
1398
1687
  typeof (self === null || self === void 0 ? void 0 : self.importScripts) === "function" &&
1399
- (((_a$1 = self.constructor) === null || _a$1 === void 0 ? void 0 : _a$1.name) === "DedicatedWorkerGlobalScope" ||
1688
+ (((_a = self.constructor) === null || _a === void 0 ? void 0 : _a.name) === "DedicatedWorkerGlobalScope" ||
1400
1689
  ((_b = self.constructor) === null || _b === void 0 ? void 0 : _b.name) === "ServiceWorkerGlobalScope" ||
1401
1690
  ((_c = self.constructor) === null || _c === void 0 ? void 0 : _c.name) === "SharedWorkerGlobalScope");
1402
1691
  /**
@@ -2011,295 +2300,6 @@ function tryProcessResponse(span, response) {
2011
2300
  }
2012
2301
  }
2013
2302
 
2014
- // Copyright (c) Microsoft Corporation.
2015
- // Licensed under the MIT license.
2016
- /**
2017
- * Helper TypeGuard that checks if something is defined or not.
2018
- * @param thing - Anything
2019
- */
2020
- function isDefined(thing) {
2021
- return typeof thing !== "undefined" && thing !== null;
2022
- }
2023
- /**
2024
- * Helper TypeGuard that checks if the input is an object with the specified properties.
2025
- * @param thing - Anything.
2026
- * @param properties - The name of the properties that should appear in the object.
2027
- */
2028
- function isObjectWithProperties(thing, properties) {
2029
- if (!isDefined(thing) || typeof thing !== "object") {
2030
- return false;
2031
- }
2032
- for (const property of properties) {
2033
- if (!objectHasProperty(thing, property)) {
2034
- return false;
2035
- }
2036
- }
2037
- return true;
2038
- }
2039
- /**
2040
- * Helper TypeGuard that checks if the input is an object with the specified property.
2041
- * @param thing - Any object.
2042
- * @param property - The name of the property that should appear in the object.
2043
- */
2044
- function objectHasProperty(thing, property) {
2045
- return (isDefined(thing) && typeof thing === "object" && property in thing);
2046
- }
2047
- function isNodeReadableStream(x) {
2048
- return Boolean(x && typeof x["pipe"] === "function");
2049
- }
2050
- function isWebReadableStream(x) {
2051
- return Boolean(x &&
2052
- typeof x.getReader === "function" &&
2053
- typeof x.tee === "function");
2054
- }
2055
- function isReadableStream$1(x) {
2056
- return isNodeReadableStream(x) || isWebReadableStream(x);
2057
- }
2058
- function isBlob(x) {
2059
- return typeof x.stream === "function";
2060
- }
2061
-
2062
- // Copyright (c) Microsoft Corporation.
2063
- // Licensed under the MIT license.
2064
- function streamAsyncIterator() {
2065
- return tslib.__asyncGenerator(this, arguments, function* streamAsyncIterator_1() {
2066
- const reader = this.getReader();
2067
- try {
2068
- while (true) {
2069
- const { done, value } = yield tslib.__await(reader.read());
2070
- if (done) {
2071
- return yield tslib.__await(void 0);
2072
- }
2073
- yield yield tslib.__await(value);
2074
- }
2075
- }
2076
- finally {
2077
- reader.releaseLock();
2078
- }
2079
- });
2080
- }
2081
- function makeAsyncIterable(webStream) {
2082
- if (!webStream[Symbol.asyncIterator]) {
2083
- webStream[Symbol.asyncIterator] = streamAsyncIterator.bind(webStream);
2084
- }
2085
- if (!webStream.values) {
2086
- webStream.values = streamAsyncIterator.bind(webStream);
2087
- }
2088
- }
2089
- function nodeStreamFromWebStream(webStream) {
2090
- makeAsyncIterable(webStream);
2091
- return stream.Readable.fromWeb(webStream);
2092
- }
2093
- function toWebStream(stream$1) {
2094
- return isWebReadableStream(stream$1)
2095
- ? stream$1
2096
- : stream.Readable.toWeb(stream.Readable.from(stream$1));
2097
- }
2098
- function toStream(source) {
2099
- if (source instanceof Uint8Array) {
2100
- return stream.Readable.from(Buffer.from(source));
2101
- }
2102
- else if (isBlob(source)) {
2103
- return nodeStreamFromWebStream(source.stream());
2104
- }
2105
- else if (isNodeReadableStream(source)) {
2106
- return source;
2107
- }
2108
- else {
2109
- return nodeStreamFromWebStream(source);
2110
- }
2111
- }
2112
- function concatenateStreams(sources) {
2113
- if (sources.some(isWebReadableStream)) {
2114
- throw new Error("Was not expecting a Web stream here");
2115
- }
2116
- return stream.Readable.from((function () {
2117
- return tslib.__asyncGenerator(this, arguments, function* () {
2118
- var _a, e_1, _b, _c;
2119
- for (const stream of sources) {
2120
- try {
2121
- for (var _d = true, stream_1 = (e_1 = void 0, tslib.__asyncValues(stream)), stream_1_1; stream_1_1 = yield tslib.__await(stream_1.next()), _a = stream_1_1.done, !_a; _d = true) {
2122
- _c = stream_1_1.value;
2123
- _d = false;
2124
- const chunk = _c;
2125
- yield yield tslib.__await(chunk);
2126
- }
2127
- }
2128
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
2129
- finally {
2130
- try {
2131
- if (!_d && !_a && (_b = stream_1.return)) yield tslib.__await(_b.call(stream_1));
2132
- }
2133
- finally { if (e_1) throw e_1.error; }
2134
- }
2135
- }
2136
- });
2137
- })());
2138
- }
2139
-
2140
- // Copyright (c) Microsoft Corporation.
2141
- // Licensed under the MIT license.
2142
- /*
2143
- * NOTE: When moving this file, please update "react-native" section in package.json.
2144
- */
2145
- /**
2146
- * Generated Universally Unique Identifier
2147
- *
2148
- * @returns RFC4122 v4 UUID.
2149
- */
2150
- function generateUUID() {
2151
- let uuid = "";
2152
- for (let i = 0; i < 32; i++) {
2153
- // Generate a random number between 0 and 15
2154
- const randomNumber = Math.floor(Math.random() * 16);
2155
- // Set the UUID version to 4 in the 13th position
2156
- if (i === 12) {
2157
- uuid += "4";
2158
- }
2159
- else if (i === 16) {
2160
- // Set the UUID variant to "10" in the 17th position
2161
- uuid += (randomNumber & 0x3) | 0x8;
2162
- }
2163
- else {
2164
- // Add a random hexadecimal digit to the UUID string
2165
- uuid += randomNumber.toString(16);
2166
- }
2167
- // Add hyphens to the UUID string at the appropriate positions
2168
- if (i === 7 || i === 11 || i === 15 || i === 19) {
2169
- uuid += "-";
2170
- }
2171
- }
2172
- return uuid;
2173
- }
2174
-
2175
- // Copyright (c) Microsoft Corporation.
2176
- // Licensed under the MIT license.
2177
- var _a;
2178
- // NOTE: This is a workaround until we can use `globalThis.crypto.randomUUID` in Node.js 19+.
2179
- let uuidFunction = typeof ((_a = globalThis === null || globalThis === void 0 ? void 0 : globalThis.crypto) === null || _a === void 0 ? void 0 : _a.randomUUID) === "function"
2180
- ? globalThis.crypto.randomUUID.bind(globalThis.crypto)
2181
- : crypto.randomUUID;
2182
- // Not defined in earlier versions of Node.js 14
2183
- if (!uuidFunction) {
2184
- uuidFunction = generateUUID;
2185
- }
2186
- /**
2187
- * Generated Universally Unique Identifier
2188
- *
2189
- * @returns RFC4122 v4 UUID.
2190
- */
2191
- function randomUUID() {
2192
- return uuidFunction();
2193
- }
2194
-
2195
- // Copyright (c) Microsoft Corporation.
2196
- // Licensed under the MIT license.
2197
- function generateBoundary() {
2198
- return `----AzSDKFormBoundary${randomUUID()}`;
2199
- }
2200
- function encodeHeaders(headers) {
2201
- let result = "";
2202
- for (const [key, value] of headers) {
2203
- result += `${key}: ${value}\r\n`;
2204
- }
2205
- return result;
2206
- }
2207
- function getLength(source) {
2208
- if (source instanceof Uint8Array) {
2209
- return source.byteLength;
2210
- }
2211
- else if (isBlob(source)) {
2212
- // if was created using createFile then -1 means we have an unknown size
2213
- return source.size === -1 ? undefined : source.size;
2214
- }
2215
- else {
2216
- return undefined;
2217
- }
2218
- }
2219
- function getTotalLength(sources) {
2220
- let total = 0;
2221
- for (const source of sources) {
2222
- const partLength = getLength(source);
2223
- if (partLength === undefined) {
2224
- return undefined;
2225
- }
2226
- else {
2227
- total += partLength;
2228
- }
2229
- }
2230
- return total;
2231
- }
2232
- function buildRequestBody(request, parts, boundary) {
2233
- const sources = [
2234
- stringToUint8Array(`--${boundary}`, "utf-8"),
2235
- ...parts.flatMap((part) => [
2236
- stringToUint8Array("\r\n", "utf-8"),
2237
- stringToUint8Array(encodeHeaders(part.headers), "utf-8"),
2238
- stringToUint8Array("\r\n", "utf-8"),
2239
- part.body,
2240
- stringToUint8Array(`\r\n--${boundary}`, "utf-8"),
2241
- ]),
2242
- stringToUint8Array("--\r\n\r\n", "utf-8"),
2243
- ];
2244
- const contentLength = getTotalLength(sources);
2245
- if (contentLength) {
2246
- request.headers.set("Content-Length", contentLength);
2247
- }
2248
- request.body = (() => concatenateStreams(sources.map((source) => (typeof source === "function" ? source() : source)).map(toStream)));
2249
- }
2250
- /**
2251
- * Name of multipart policy
2252
- */
2253
- const multipartPolicyName = "multipartPolicy";
2254
- const maxBoundaryLength = 70;
2255
- const validBoundaryCharacters = new Set(`abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'()+,-./:=?`);
2256
- function assertValidBoundary(boundary) {
2257
- if (boundary.length > maxBoundaryLength) {
2258
- throw new Error(`Multipart boundary "${boundary}" exceeds maximum length of 70 characters`);
2259
- }
2260
- if (Array.from(boundary).some((x) => !validBoundaryCharacters.has(x))) {
2261
- throw new Error(`Multipart boundary "${boundary}" contains invalid characters`);
2262
- }
2263
- }
2264
- /**
2265
- * Pipeline policy for multipart requests
2266
- */
2267
- function multipartPolicy() {
2268
- return {
2269
- name: multipartPolicyName,
2270
- sendRequest(request, next) {
2271
- var _a;
2272
- if (!request.multipartBody) {
2273
- return next(request);
2274
- }
2275
- if (request.body) {
2276
- throw new Error("multipartBody and regular body cannot be set at the same time");
2277
- }
2278
- let boundary = request.multipartBody.boundary;
2279
- const contentTypeHeader = (_a = request.headers.get("Content-Type")) !== null && _a !== void 0 ? _a : "multipart/mixed";
2280
- const parsedHeader = contentTypeHeader.match(/^(multipart\/[^ ;]+)(?:; *boundary=(.+))?$/);
2281
- if (!parsedHeader) {
2282
- throw new Error(`Got multipart request body, but content-type header was not multipart: ${contentTypeHeader}`);
2283
- }
2284
- const [, contentType, parsedBoundary] = parsedHeader;
2285
- if (parsedBoundary && boundary && parsedBoundary !== boundary) {
2286
- throw new Error(`Multipart boundary was specified as ${parsedBoundary} in the header, but got ${boundary} in the request body`);
2287
- }
2288
- boundary !== null && boundary !== void 0 ? boundary : (boundary = parsedBoundary);
2289
- if (boundary) {
2290
- assertValidBoundary(boundary);
2291
- }
2292
- else {
2293
- boundary = generateBoundary();
2294
- }
2295
- request.headers.set("Content-Type", `${contentType}; boundary=${boundary}`);
2296
- buildRequestBody(request, request.multipartBody.parts, boundary);
2297
- request.multipartBody = undefined;
2298
- return next(request);
2299
- },
2300
- };
2301
- }
2302
-
2303
2303
  // Copyright (c) Microsoft Corporation.
2304
2304
  // Licensed under the MIT license.
2305
2305
  /**
@@ -2315,7 +2315,7 @@ function createPipelineFromOptions(options) {
2315
2315
  pipeline.addPolicy(proxyPolicy(options.proxyOptions));
2316
2316
  pipeline.addPolicy(decompressResponsePolicy());
2317
2317
  }
2318
- pipeline.addPolicy(formDataPolicy());
2318
+ pipeline.addPolicy(formDataPolicy(), { beforePolicies: [multipartPolicyName] });
2319
2319
  pipeline.addPolicy(userAgentPolicy(options.userAgentOptions));
2320
2320
  // The multipart policy is added after policies with no phase, so that
2321
2321
  // policies can be added between it and formDataPolicy to modify