mirror of
https://github.com/oven-sh/setup-bun.git
synced 2025-07-19 04:58:25 +02:00
feat: add @actions/cache
This commit is contained in:
parent
b15fb7d098
commit
16e8c96a41
1932 changed files with 261172 additions and 10 deletions
33
node_modules/@azure/ms-rest-js/lib/policies/agentPolicy.browser.ts
generated
vendored
Normal file
33
node_modules/@azure/ms-rest-js/lib/policies/agentPolicy.browser.ts
generated
vendored
Normal file
|
@ -0,0 +1,33 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
import { AgentSettings } from "../serviceClient";
|
||||
import {
|
||||
BaseRequestPolicy,
|
||||
RequestPolicy,
|
||||
RequestPolicyFactory,
|
||||
RequestPolicyOptionsLike,
|
||||
} from "./requestPolicy";
|
||||
import { HttpOperationResponse } from "../httpOperationResponse";
|
||||
import { WebResourceLike } from "../webResource";
|
||||
|
||||
const agentNotSupportedInBrowser = new Error("AgentPolicy is not supported in browser environment");
|
||||
|
||||
export function agentPolicy(_agentSettings?: AgentSettings): RequestPolicyFactory {
|
||||
return {
|
||||
create: (_nextPolicy: RequestPolicy, _options: RequestPolicyOptionsLike) => {
|
||||
throw agentNotSupportedInBrowser;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export class AgentPolicy extends BaseRequestPolicy {
|
||||
constructor(nextPolicy: RequestPolicy, options: RequestPolicyOptionsLike) {
|
||||
super(nextPolicy, options);
|
||||
throw agentNotSupportedInBrowser;
|
||||
}
|
||||
|
||||
public sendRequest(_request: WebResourceLike): Promise<HttpOperationResponse> {
|
||||
throw agentNotSupportedInBrowser;
|
||||
}
|
||||
}
|
40
node_modules/@azure/ms-rest-js/lib/policies/agentPolicy.ts
generated
vendored
Normal file
40
node_modules/@azure/ms-rest-js/lib/policies/agentPolicy.ts
generated
vendored
Normal file
|
@ -0,0 +1,40 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
import { AgentSettings } from "../serviceClient";
|
||||
import {
|
||||
BaseRequestPolicy,
|
||||
RequestPolicy,
|
||||
RequestPolicyFactory,
|
||||
RequestPolicyOptionsLike,
|
||||
} from "./requestPolicy";
|
||||
import { HttpOperationResponse } from "../httpOperationResponse";
|
||||
import { WebResourceLike } from "../webResource";
|
||||
|
||||
export function agentPolicy(agentSettings?: AgentSettings): RequestPolicyFactory {
|
||||
return {
|
||||
create: (nextPolicy: RequestPolicy, options: RequestPolicyOptionsLike) => {
|
||||
return new AgentPolicy(nextPolicy, options, agentSettings!);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export class AgentPolicy extends BaseRequestPolicy {
|
||||
agentSettings: AgentSettings;
|
||||
|
||||
constructor(
|
||||
nextPolicy: RequestPolicy,
|
||||
options: RequestPolicyOptionsLike,
|
||||
agentSettings: AgentSettings
|
||||
) {
|
||||
super(nextPolicy, options);
|
||||
this.agentSettings = agentSettings;
|
||||
}
|
||||
|
||||
public sendRequest(request: WebResourceLike): Promise<HttpOperationResponse> {
|
||||
if (!request.agentSettings) {
|
||||
request.agentSettings = this.agentSettings;
|
||||
}
|
||||
return this._nextPolicy.sendRequest(request);
|
||||
}
|
||||
}
|
294
node_modules/@azure/ms-rest-js/lib/policies/deserializationPolicy.ts
generated
vendored
Normal file
294
node_modules/@azure/ms-rest-js/lib/policies/deserializationPolicy.ts
generated
vendored
Normal file
|
@ -0,0 +1,294 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
import { HttpOperationResponse } from "../httpOperationResponse";
|
||||
import { OperationResponse } from "../operationResponse";
|
||||
import { OperationSpec, isStreamOperation } from "../operationSpec";
|
||||
import { RestError } from "../restError";
|
||||
import { Mapper, MapperType } from "../serializer";
|
||||
import * as utils from "../util/utils";
|
||||
import { parseXML } from "../util/xml";
|
||||
import { WebResourceLike } from "../webResource";
|
||||
import {
|
||||
BaseRequestPolicy,
|
||||
RequestPolicy,
|
||||
RequestPolicyFactory,
|
||||
RequestPolicyOptionsLike,
|
||||
} from "./requestPolicy";
|
||||
|
||||
/**
|
||||
* The content-types that will indicate that an operation response should be deserialized in a
|
||||
* particular way.
|
||||
*/
|
||||
export interface DeserializationContentTypes {
|
||||
/**
|
||||
* The content-types that indicate that an operation response should be deserialized as JSON.
|
||||
* Defaults to [ "application/json", "text/json" ].
|
||||
*/
|
||||
json?: string[];
|
||||
|
||||
/**
|
||||
* The content-types that indicate that an operation response should be deserialized as XML.
|
||||
* Defaults to [ "application/xml", "application/atom+xml" ].
|
||||
*/
|
||||
xml?: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new serialization RequestPolicyCreator that will serialized HTTP request bodies as they
|
||||
* pass through the HTTP pipeline.
|
||||
*/
|
||||
export function deserializationPolicy(
|
||||
deserializationContentTypes?: DeserializationContentTypes
|
||||
): RequestPolicyFactory {
|
||||
return {
|
||||
create: (nextPolicy: RequestPolicy, options: RequestPolicyOptionsLike) => {
|
||||
return new DeserializationPolicy(nextPolicy, deserializationContentTypes, options);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export const defaultJsonContentTypes = ["application/json", "text/json"];
|
||||
export const defaultXmlContentTypes = ["application/xml", "application/atom+xml"];
|
||||
|
||||
/**
|
||||
* A RequestPolicy that will deserialize HTTP response bodies and headers as they pass through the
|
||||
* HTTP pipeline.
|
||||
*/
|
||||
export class DeserializationPolicy extends BaseRequestPolicy {
|
||||
public readonly jsonContentTypes: string[];
|
||||
public readonly xmlContentTypes: string[];
|
||||
|
||||
constructor(
|
||||
nextPolicy: RequestPolicy,
|
||||
deserializationContentTypes: DeserializationContentTypes | undefined,
|
||||
options: RequestPolicyOptionsLike
|
||||
) {
|
||||
super(nextPolicy, options);
|
||||
|
||||
this.jsonContentTypes =
|
||||
(deserializationContentTypes && deserializationContentTypes.json) || defaultJsonContentTypes;
|
||||
this.xmlContentTypes =
|
||||
(deserializationContentTypes && deserializationContentTypes.xml) || defaultXmlContentTypes;
|
||||
}
|
||||
|
||||
public async sendRequest(request: WebResourceLike): Promise<HttpOperationResponse> {
|
||||
return this._nextPolicy
|
||||
.sendRequest(request)
|
||||
.then((response: HttpOperationResponse) =>
|
||||
deserializeResponseBody(this.jsonContentTypes, this.xmlContentTypes, response)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function getOperationResponse(
|
||||
parsedResponse: HttpOperationResponse
|
||||
): undefined | OperationResponse {
|
||||
let result: OperationResponse | undefined;
|
||||
const request: WebResourceLike = parsedResponse.request;
|
||||
const operationSpec: OperationSpec | undefined = request.operationSpec;
|
||||
if (operationSpec) {
|
||||
const operationResponseGetter:
|
||||
| undefined
|
||||
| ((
|
||||
operationSpec: OperationSpec,
|
||||
response: HttpOperationResponse
|
||||
) => undefined | OperationResponse) = request.operationResponseGetter;
|
||||
if (!operationResponseGetter) {
|
||||
result = operationSpec.responses[parsedResponse.status];
|
||||
} else {
|
||||
result = operationResponseGetter(operationSpec, parsedResponse);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function shouldDeserializeResponse(parsedResponse: HttpOperationResponse): boolean {
|
||||
const shouldDeserialize: undefined | boolean | ((response: HttpOperationResponse) => boolean) =
|
||||
parsedResponse.request.shouldDeserialize;
|
||||
let result: boolean;
|
||||
if (shouldDeserialize === undefined) {
|
||||
result = true;
|
||||
} else if (typeof shouldDeserialize === "boolean") {
|
||||
result = shouldDeserialize;
|
||||
} else {
|
||||
result = shouldDeserialize(parsedResponse);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function deserializeResponseBody(
|
||||
jsonContentTypes: string[],
|
||||
xmlContentTypes: string[],
|
||||
response: HttpOperationResponse
|
||||
): Promise<HttpOperationResponse> {
|
||||
return parse(jsonContentTypes, xmlContentTypes, response).then((parsedResponse) => {
|
||||
const shouldDeserialize: boolean = shouldDeserializeResponse(parsedResponse);
|
||||
if (shouldDeserialize) {
|
||||
const operationSpec: OperationSpec | undefined = parsedResponse.request.operationSpec;
|
||||
if (operationSpec && operationSpec.responses) {
|
||||
const statusCode: number = parsedResponse.status;
|
||||
|
||||
const expectedStatusCodes: string[] = Object.keys(operationSpec.responses);
|
||||
|
||||
const hasNoExpectedStatusCodes: boolean =
|
||||
expectedStatusCodes.length === 0 ||
|
||||
(expectedStatusCodes.length === 1 && expectedStatusCodes[0] === "default");
|
||||
|
||||
const responseSpec: OperationResponse | undefined = getOperationResponse(parsedResponse);
|
||||
|
||||
const isExpectedStatusCode: boolean = hasNoExpectedStatusCodes
|
||||
? 200 <= statusCode && statusCode < 300
|
||||
: !!responseSpec;
|
||||
if (!isExpectedStatusCode) {
|
||||
const defaultResponseSpec: OperationResponse = operationSpec.responses.default;
|
||||
if (defaultResponseSpec) {
|
||||
const initialErrorMessage: string = isStreamOperation(operationSpec)
|
||||
? `Unexpected status code: ${statusCode}`
|
||||
: (parsedResponse.bodyAsText as string);
|
||||
|
||||
const error = new RestError(initialErrorMessage);
|
||||
error.statusCode = statusCode;
|
||||
error.request = utils.stripRequest(parsedResponse.request);
|
||||
error.response = utils.stripResponse(parsedResponse);
|
||||
|
||||
let parsedErrorResponse: { [key: string]: any } = parsedResponse.parsedBody;
|
||||
try {
|
||||
if (parsedErrorResponse) {
|
||||
const defaultResponseBodyMapper: Mapper | undefined =
|
||||
defaultResponseSpec.bodyMapper;
|
||||
if (
|
||||
defaultResponseBodyMapper &&
|
||||
defaultResponseBodyMapper.serializedName === "CloudError"
|
||||
) {
|
||||
if (parsedErrorResponse.error) {
|
||||
parsedErrorResponse = parsedErrorResponse.error;
|
||||
}
|
||||
if (parsedErrorResponse.code) {
|
||||
error.code = parsedErrorResponse.code;
|
||||
}
|
||||
if (parsedErrorResponse.message) {
|
||||
error.message = parsedErrorResponse.message;
|
||||
}
|
||||
} else {
|
||||
let internalError: any = parsedErrorResponse;
|
||||
if (parsedErrorResponse.error) {
|
||||
internalError = parsedErrorResponse.error;
|
||||
}
|
||||
|
||||
error.code = internalError.code;
|
||||
if (internalError.message) {
|
||||
error.message = internalError.message;
|
||||
}
|
||||
}
|
||||
|
||||
if (defaultResponseBodyMapper) {
|
||||
let valueToDeserialize: any = parsedErrorResponse;
|
||||
if (
|
||||
operationSpec.isXML &&
|
||||
defaultResponseBodyMapper.type.name === MapperType.Sequence
|
||||
) {
|
||||
valueToDeserialize =
|
||||
typeof parsedErrorResponse === "object"
|
||||
? parsedErrorResponse[defaultResponseBodyMapper.xmlElementName!]
|
||||
: [];
|
||||
}
|
||||
error.body = operationSpec.serializer.deserialize(
|
||||
defaultResponseBodyMapper,
|
||||
valueToDeserialize,
|
||||
"error.body"
|
||||
);
|
||||
}
|
||||
}
|
||||
} catch (defaultError) {
|
||||
error.message = `Error \"${defaultError.message}\" occurred in deserializing the responseBody - \"${parsedResponse.bodyAsText}\" for the default response.`;
|
||||
}
|
||||
return Promise.reject(error);
|
||||
}
|
||||
} else if (responseSpec) {
|
||||
if (responseSpec.bodyMapper) {
|
||||
let valueToDeserialize: any = parsedResponse.parsedBody;
|
||||
if (operationSpec.isXML && responseSpec.bodyMapper.type.name === MapperType.Sequence) {
|
||||
valueToDeserialize =
|
||||
typeof valueToDeserialize === "object"
|
||||
? valueToDeserialize[responseSpec.bodyMapper.xmlElementName!]
|
||||
: [];
|
||||
}
|
||||
try {
|
||||
parsedResponse.parsedBody = operationSpec.serializer.deserialize(
|
||||
responseSpec.bodyMapper,
|
||||
valueToDeserialize,
|
||||
"operationRes.parsedBody"
|
||||
);
|
||||
} catch (error) {
|
||||
const restError = new RestError(
|
||||
`Error ${error} occurred in deserializing the responseBody - ${parsedResponse.bodyAsText}`
|
||||
);
|
||||
restError.request = utils.stripRequest(parsedResponse.request);
|
||||
restError.response = utils.stripResponse(parsedResponse);
|
||||
return Promise.reject(restError);
|
||||
}
|
||||
} else if (operationSpec.httpMethod === "HEAD") {
|
||||
// head methods never have a body, but we return a boolean to indicate presence/absence of the resource
|
||||
parsedResponse.parsedBody = response.status >= 200 && response.status < 300;
|
||||
}
|
||||
|
||||
if (responseSpec.headersMapper) {
|
||||
parsedResponse.parsedHeaders = operationSpec.serializer.deserialize(
|
||||
responseSpec.headersMapper,
|
||||
parsedResponse.headers.rawHeaders(),
|
||||
"operationRes.parsedHeaders"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return Promise.resolve(parsedResponse);
|
||||
});
|
||||
}
|
||||
|
||||
function parse(
|
||||
jsonContentTypes: string[],
|
||||
xmlContentTypes: string[],
|
||||
operationResponse: HttpOperationResponse
|
||||
): Promise<HttpOperationResponse> {
|
||||
const errorHandler = (err: Error & { code: string }) => {
|
||||
const msg = `Error "${err}" occurred while parsing the response body - ${operationResponse.bodyAsText}.`;
|
||||
const errCode = err.code || RestError.PARSE_ERROR;
|
||||
const e = new RestError(
|
||||
msg,
|
||||
errCode,
|
||||
operationResponse.status,
|
||||
operationResponse.request,
|
||||
operationResponse,
|
||||
operationResponse.bodyAsText
|
||||
);
|
||||
return Promise.reject(e);
|
||||
};
|
||||
|
||||
if (!operationResponse.request.streamResponseBody && operationResponse.bodyAsText) {
|
||||
const text = operationResponse.bodyAsText;
|
||||
const contentType: string = operationResponse.headers.get("Content-Type") || "";
|
||||
const contentComponents: string[] = !contentType
|
||||
? []
|
||||
: contentType.split(";").map((component) => component.toLowerCase());
|
||||
if (
|
||||
contentComponents.length === 0 ||
|
||||
contentComponents.some((component) => jsonContentTypes.indexOf(component) !== -1)
|
||||
) {
|
||||
return new Promise<HttpOperationResponse>((resolve) => {
|
||||
operationResponse.parsedBody = JSON.parse(text);
|
||||
resolve(operationResponse);
|
||||
}).catch(errorHandler);
|
||||
} else if (contentComponents.some((component) => xmlContentTypes.indexOf(component) !== -1)) {
|
||||
return parseXML(text)
|
||||
.then((body) => {
|
||||
operationResponse.parsedBody = body;
|
||||
return operationResponse;
|
||||
})
|
||||
.catch(errorHandler);
|
||||
}
|
||||
}
|
||||
|
||||
return Promise.resolve(operationResponse);
|
||||
}
|
220
node_modules/@azure/ms-rest-js/lib/policies/exponentialRetryPolicy.ts
generated
vendored
Normal file
220
node_modules/@azure/ms-rest-js/lib/policies/exponentialRetryPolicy.ts
generated
vendored
Normal file
|
@ -0,0 +1,220 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
import { HttpOperationResponse } from "../httpOperationResponse";
|
||||
import * as utils from "../util/utils";
|
||||
import { WebResourceLike } from "../webResource";
|
||||
import {
|
||||
BaseRequestPolicy,
|
||||
RequestPolicy,
|
||||
RequestPolicyFactory,
|
||||
RequestPolicyOptionsLike,
|
||||
} from "./requestPolicy";
|
||||
import { RestError } from "../restError";
|
||||
|
||||
export interface RetryData {
|
||||
retryCount: number;
|
||||
retryInterval: number;
|
||||
error?: RetryError;
|
||||
}
|
||||
|
||||
export interface RetryError extends Error {
|
||||
message: string;
|
||||
code?: string;
|
||||
innerError?: RetryError;
|
||||
}
|
||||
|
||||
export function exponentialRetryPolicy(
|
||||
retryCount?: number,
|
||||
retryInterval?: number,
|
||||
minRetryInterval?: number,
|
||||
maxRetryInterval?: number
|
||||
): RequestPolicyFactory {
|
||||
return {
|
||||
create: (nextPolicy: RequestPolicy, options: RequestPolicyOptionsLike) => {
|
||||
return new ExponentialRetryPolicy(
|
||||
nextPolicy,
|
||||
options,
|
||||
retryCount,
|
||||
retryInterval,
|
||||
minRetryInterval,
|
||||
maxRetryInterval
|
||||
);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const DEFAULT_CLIENT_RETRY_INTERVAL = 1000 * 30;
|
||||
const DEFAULT_CLIENT_RETRY_COUNT = 3;
|
||||
const DEFAULT_CLIENT_MAX_RETRY_INTERVAL = 1000 * 90;
|
||||
const DEFAULT_CLIENT_MIN_RETRY_INTERVAL = 1000 * 3;
|
||||
|
||||
/**
|
||||
* @class
|
||||
* Instantiates a new "ExponentialRetryPolicyFilter" instance.
|
||||
*/
|
||||
export class ExponentialRetryPolicy extends BaseRequestPolicy {
|
||||
/**
|
||||
* The client retry count.
|
||||
*/
|
||||
retryCount: number;
|
||||
/**
|
||||
* The client retry interval in milliseconds.
|
||||
*/
|
||||
retryInterval: number;
|
||||
/**
|
||||
* The minimum retry interval in milliseconds.
|
||||
*/
|
||||
minRetryInterval: number;
|
||||
/**
|
||||
* The maximum retry interval in milliseconds.
|
||||
*/
|
||||
maxRetryInterval: number;
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @param {RequestPolicy} nextPolicy The next RequestPolicy in the pipeline chain.
|
||||
* @param {RequestPolicyOptionsLike} options The options for this RequestPolicy.
|
||||
* @param {number} [retryCount] The client retry count.
|
||||
* @param {number} [retryInterval] The client retry interval, in milliseconds.
|
||||
* @param {number} [minRetryInterval] The minimum retry interval, in milliseconds.
|
||||
* @param {number} [maxRetryInterval] The maximum retry interval, in milliseconds.
|
||||
*/
|
||||
constructor(
|
||||
nextPolicy: RequestPolicy,
|
||||
options: RequestPolicyOptionsLike,
|
||||
retryCount?: number,
|
||||
retryInterval?: number,
|
||||
minRetryInterval?: number,
|
||||
maxRetryInterval?: number
|
||||
) {
|
||||
super(nextPolicy, options);
|
||||
function isNumber(n: any): n is number {
|
||||
return typeof n === "number";
|
||||
}
|
||||
this.retryCount = isNumber(retryCount) ? retryCount : DEFAULT_CLIENT_RETRY_COUNT;
|
||||
this.retryInterval = isNumber(retryInterval) ? retryInterval : DEFAULT_CLIENT_RETRY_INTERVAL;
|
||||
this.minRetryInterval = isNumber(minRetryInterval)
|
||||
? minRetryInterval
|
||||
: DEFAULT_CLIENT_MIN_RETRY_INTERVAL;
|
||||
this.maxRetryInterval = isNumber(maxRetryInterval)
|
||||
? maxRetryInterval
|
||||
: DEFAULT_CLIENT_MAX_RETRY_INTERVAL;
|
||||
}
|
||||
|
||||
public sendRequest(request: WebResourceLike): Promise<HttpOperationResponse> {
|
||||
return this._nextPolicy
|
||||
.sendRequest(request.clone())
|
||||
.then((response) => retry(this, request, response))
|
||||
.catch((error) => retry(this, request, error.response, undefined, error));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the operation should be retried and how long to wait until the next retry.
|
||||
*
|
||||
* @param {ExponentialRetryPolicy} policy The ExponentialRetryPolicy that this function is being called against.
|
||||
* @param {number} statusCode The HTTP status code.
|
||||
* @param {RetryData} retryData The retry data.
|
||||
* @return {boolean} True if the operation qualifies for a retry; false otherwise.
|
||||
*/
|
||||
function shouldRetry(
|
||||
policy: ExponentialRetryPolicy,
|
||||
statusCode: number | undefined,
|
||||
retryData: RetryData
|
||||
): boolean {
|
||||
if (
|
||||
statusCode == undefined ||
|
||||
(statusCode < 500 && statusCode !== 408) ||
|
||||
statusCode === 501 ||
|
||||
statusCode === 505
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let currentCount: number;
|
||||
if (!retryData) {
|
||||
throw new Error("retryData for the ExponentialRetryPolicyFilter cannot be null.");
|
||||
} else {
|
||||
currentCount = retryData && retryData.retryCount;
|
||||
}
|
||||
|
||||
return currentCount < policy.retryCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the retry data for the next attempt.
|
||||
*
|
||||
* @param {ExponentialRetryPolicy} policy The ExponentialRetryPolicy that this function is being called against.
|
||||
* @param {RetryData} retryData The retry data.
|
||||
* @param {RetryError} [err] The operation"s error, if any.
|
||||
*/
|
||||
function updateRetryData(
|
||||
policy: ExponentialRetryPolicy,
|
||||
retryData?: RetryData,
|
||||
err?: RetryError
|
||||
): RetryData {
|
||||
if (!retryData) {
|
||||
retryData = {
|
||||
retryCount: 0,
|
||||
retryInterval: 0,
|
||||
};
|
||||
}
|
||||
|
||||
if (err) {
|
||||
if (retryData.error) {
|
||||
err.innerError = retryData.error;
|
||||
}
|
||||
|
||||
retryData.error = err;
|
||||
}
|
||||
|
||||
// Adjust retry count
|
||||
retryData.retryCount++;
|
||||
|
||||
// Adjust retry interval
|
||||
let incrementDelta = Math.pow(2, retryData.retryCount) - 1;
|
||||
const boundedRandDelta =
|
||||
policy.retryInterval * 0.8 +
|
||||
Math.floor(Math.random() * (policy.retryInterval * 1.2 - policy.retryInterval * 0.8));
|
||||
incrementDelta *= boundedRandDelta;
|
||||
|
||||
retryData.retryInterval = Math.min(
|
||||
policy.minRetryInterval + incrementDelta,
|
||||
policy.maxRetryInterval
|
||||
);
|
||||
|
||||
return retryData;
|
||||
}
|
||||
|
||||
function retry(
|
||||
policy: ExponentialRetryPolicy,
|
||||
request: WebResourceLike,
|
||||
response?: HttpOperationResponse,
|
||||
retryData?: RetryData,
|
||||
requestError?: RetryError
|
||||
): Promise<HttpOperationResponse> {
|
||||
retryData = updateRetryData(policy, retryData, requestError);
|
||||
const isAborted: boolean | undefined = request.abortSignal && request.abortSignal.aborted;
|
||||
if (!isAborted && shouldRetry(policy, response && response.status, retryData)) {
|
||||
return utils
|
||||
.delay(retryData.retryInterval)
|
||||
.then(() => policy._nextPolicy.sendRequest(request.clone()))
|
||||
.then((res) => retry(policy, request, res, retryData, undefined))
|
||||
.catch((err) => retry(policy, request, response, retryData, err));
|
||||
} else if (isAborted || requestError || !response) {
|
||||
// If the operation failed in the end, return all errors instead of just the last one
|
||||
const err =
|
||||
retryData.error ||
|
||||
new RestError(
|
||||
"Failed to send the request.",
|
||||
RestError.REQUEST_SEND_ERROR,
|
||||
response && response.status,
|
||||
response && response.request,
|
||||
response
|
||||
);
|
||||
return Promise.reject(err);
|
||||
} else {
|
||||
return Promise.resolve(response);
|
||||
}
|
||||
}
|
39
node_modules/@azure/ms-rest-js/lib/policies/generateClientRequestIdPolicy.ts
generated
vendored
Normal file
39
node_modules/@azure/ms-rest-js/lib/policies/generateClientRequestIdPolicy.ts
generated
vendored
Normal file
|
@ -0,0 +1,39 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
import { HttpOperationResponse } from "../httpOperationResponse";
|
||||
import * as utils from "../util/utils";
|
||||
import { WebResourceLike } from "../webResource";
|
||||
import {
|
||||
BaseRequestPolicy,
|
||||
RequestPolicy,
|
||||
RequestPolicyFactory,
|
||||
RequestPolicyOptionsLike,
|
||||
} from "./requestPolicy";
|
||||
|
||||
export function generateClientRequestIdPolicy(
|
||||
requestIdHeaderName = "x-ms-client-request-id"
|
||||
): RequestPolicyFactory {
|
||||
return {
|
||||
create: (nextPolicy: RequestPolicy, options: RequestPolicyOptionsLike) => {
|
||||
return new GenerateClientRequestIdPolicy(nextPolicy, options, requestIdHeaderName);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export class GenerateClientRequestIdPolicy extends BaseRequestPolicy {
|
||||
constructor(
|
||||
nextPolicy: RequestPolicy,
|
||||
options: RequestPolicyOptionsLike,
|
||||
private _requestIdHeaderName: string
|
||||
) {
|
||||
super(nextPolicy, options);
|
||||
}
|
||||
|
||||
public sendRequest(request: WebResourceLike): Promise<HttpOperationResponse> {
|
||||
if (!request.headers.contains(this._requestIdHeaderName)) {
|
||||
request.headers.set(this._requestIdHeaderName, utils.generateUuid());
|
||||
}
|
||||
return this._nextPolicy.sendRequest(request);
|
||||
}
|
||||
}
|
47
node_modules/@azure/ms-rest-js/lib/policies/logPolicy.ts
generated
vendored
Normal file
47
node_modules/@azure/ms-rest-js/lib/policies/logPolicy.ts
generated
vendored
Normal file
|
@ -0,0 +1,47 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
import { HttpOperationResponse } from "../httpOperationResponse";
|
||||
import { WebResourceLike } from "../webResource";
|
||||
import {
|
||||
BaseRequestPolicy,
|
||||
RequestPolicy,
|
||||
RequestPolicyFactory,
|
||||
RequestPolicyOptionsLike,
|
||||
} from "./requestPolicy";
|
||||
|
||||
export function logPolicy(logger: any = console.log): RequestPolicyFactory {
|
||||
return {
|
||||
create: (nextPolicy: RequestPolicy, options: RequestPolicyOptionsLike) => {
|
||||
return new LogPolicy(nextPolicy, options, logger);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export class LogPolicy extends BaseRequestPolicy {
|
||||
logger?: any;
|
||||
|
||||
constructor(
|
||||
nextPolicy: RequestPolicy,
|
||||
options: RequestPolicyOptionsLike,
|
||||
logger: any = console.log
|
||||
) {
|
||||
super(nextPolicy, options);
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
public sendRequest(request: WebResourceLike): Promise<HttpOperationResponse> {
|
||||
return this._nextPolicy.sendRequest(request).then((response) => logResponse(this, response));
|
||||
}
|
||||
}
|
||||
|
||||
function logResponse(
|
||||
policy: LogPolicy,
|
||||
response: HttpOperationResponse
|
||||
): Promise<HttpOperationResponse> {
|
||||
policy.logger(`>> Request: ${JSON.stringify(response.request, undefined, 2)}`);
|
||||
policy.logger(`>> Response status code: ${response.status}`);
|
||||
const responseBody = response.bodyAsText;
|
||||
policy.logger(`>> Body: ${responseBody}`);
|
||||
return Promise.resolve(response);
|
||||
}
|
28
node_modules/@azure/ms-rest-js/lib/policies/msRestUserAgentPolicy.browser.ts
generated
vendored
Normal file
28
node_modules/@azure/ms-rest-js/lib/policies/msRestUserAgentPolicy.browser.ts
generated
vendored
Normal file
|
@ -0,0 +1,28 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
/*
|
||||
* NOTE: When moving this file, please update "browser" section in package.json
|
||||
* and "plugins" section in webpack.testconfig.ts.
|
||||
*/
|
||||
|
||||
import { TelemetryInfo } from "./userAgentPolicy";
|
||||
|
||||
interface NavigatorEx extends Navigator {
|
||||
// oscpu is not yet standards-compliant, but can not be undefined in TypeScript 3.6.2
|
||||
readonly oscpu: string;
|
||||
}
|
||||
|
||||
export function getDefaultUserAgentKey(): string {
|
||||
return "x-ms-command-name";
|
||||
}
|
||||
|
||||
export function getPlatformSpecificData(): TelemetryInfo[] {
|
||||
const navigator = self.navigator as NavigatorEx;
|
||||
const osInfo = {
|
||||
key: "OS",
|
||||
value: (navigator.oscpu || navigator.platform).replace(" ", ""),
|
||||
};
|
||||
|
||||
return [osInfo];
|
||||
}
|
24
node_modules/@azure/ms-rest-js/lib/policies/msRestUserAgentPolicy.ts
generated
vendored
Normal file
24
node_modules/@azure/ms-rest-js/lib/policies/msRestUserAgentPolicy.ts
generated
vendored
Normal file
|
@ -0,0 +1,24 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
import * as os from "os";
|
||||
import { TelemetryInfo } from "./userAgentPolicy";
|
||||
import { Constants } from "../util/constants";
|
||||
|
||||
export function getDefaultUserAgentKey(): string {
|
||||
return Constants.HeaderConstants.USER_AGENT;
|
||||
}
|
||||
|
||||
export function getPlatformSpecificData(): TelemetryInfo[] {
|
||||
const runtimeInfo = {
|
||||
key: "Node",
|
||||
value: process.version,
|
||||
};
|
||||
|
||||
const osInfo = {
|
||||
key: "OS",
|
||||
value: `(${os.arch()}-${os.type()}-${os.release()})`,
|
||||
};
|
||||
|
||||
return [runtimeInfo, osInfo];
|
||||
}
|
37
node_modules/@azure/ms-rest-js/lib/policies/proxyPolicy.browser.ts
generated
vendored
Normal file
37
node_modules/@azure/ms-rest-js/lib/policies/proxyPolicy.browser.ts
generated
vendored
Normal file
|
@ -0,0 +1,37 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
import { ProxySettings } from "../serviceClient";
|
||||
import {
|
||||
BaseRequestPolicy,
|
||||
RequestPolicy,
|
||||
RequestPolicyFactory,
|
||||
RequestPolicyOptionsLike,
|
||||
} from "./requestPolicy";
|
||||
import { HttpOperationResponse } from "../httpOperationResponse";
|
||||
import { WebResourceLike } from "../webResource";
|
||||
|
||||
const proxyNotSupportedInBrowser = new Error("ProxyPolicy is not supported in browser environment");
|
||||
|
||||
export function getDefaultProxySettings(_proxyUrl?: string): ProxySettings | undefined {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export function proxyPolicy(_proxySettings?: ProxySettings): RequestPolicyFactory {
|
||||
return {
|
||||
create: (_nextPolicy: RequestPolicy, _options: RequestPolicyOptionsLike) => {
|
||||
throw proxyNotSupportedInBrowser;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export class ProxyPolicy extends BaseRequestPolicy {
|
||||
constructor(nextPolicy: RequestPolicy, options: RequestPolicyOptionsLike) {
|
||||
super(nextPolicy, options);
|
||||
throw proxyNotSupportedInBrowser;
|
||||
}
|
||||
|
||||
public sendRequest(_request: WebResourceLike): Promise<HttpOperationResponse> {
|
||||
throw proxyNotSupportedInBrowser;
|
||||
}
|
||||
}
|
168
node_modules/@azure/ms-rest-js/lib/policies/proxyPolicy.ts
generated
vendored
Normal file
168
node_modules/@azure/ms-rest-js/lib/policies/proxyPolicy.ts
generated
vendored
Normal file
|
@ -0,0 +1,168 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
import {
|
||||
BaseRequestPolicy,
|
||||
RequestPolicy,
|
||||
RequestPolicyFactory,
|
||||
RequestPolicyOptionsLike,
|
||||
} from "./requestPolicy";
|
||||
import { HttpOperationResponse } from "../httpOperationResponse";
|
||||
import { ProxySettings } from "../serviceClient";
|
||||
import { WebResourceLike } from "../webResource";
|
||||
import { Constants } from "../util/constants";
|
||||
import { URLBuilder } from "../url";
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export const noProxyList: string[] = loadNoProxy();
|
||||
const byPassedList: Map<string, boolean> = new Map();
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export function getEnvironmentValue(name: string): string | undefined {
|
||||
if (process.env[name]) {
|
||||
return process.env[name];
|
||||
} else if (process.env[name.toLowerCase()]) {
|
||||
return process.env[name.toLowerCase()];
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function loadEnvironmentProxyValue(): string | undefined {
|
||||
if (!process) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const httpsProxy = getEnvironmentValue(Constants.HTTPS_PROXY);
|
||||
const allProxy = getEnvironmentValue(Constants.ALL_PROXY);
|
||||
const httpProxy = getEnvironmentValue(Constants.HTTP_PROXY);
|
||||
|
||||
return httpsProxy || allProxy || httpProxy;
|
||||
}
|
||||
|
||||
// Check whether the host of a given `uri` is in the noProxyList.
|
||||
// If there's a match, any request sent to the same host won't have the proxy settings set.
|
||||
// This implementation is a port of https://github.com/Azure/azure-sdk-for-net/blob/8cca811371159e527159c7eb65602477898683e2/sdk/core/Azure.Core/src/Pipeline/Internal/HttpEnvironmentProxy.cs#L210
|
||||
function isBypassed(uri: string): boolean | undefined {
|
||||
if (noProxyList.length === 0) {
|
||||
return false;
|
||||
}
|
||||
const host = URLBuilder.parse(uri).getHost()!;
|
||||
if (byPassedList.has(host)) {
|
||||
return byPassedList.get(host);
|
||||
}
|
||||
let isBypassedFlag = false;
|
||||
for (const pattern of noProxyList) {
|
||||
if (pattern[0] === ".") {
|
||||
// This should match either domain it self or any subdomain or host
|
||||
// .foo.com will match foo.com it self or *.foo.com
|
||||
if (host.endsWith(pattern)) {
|
||||
isBypassedFlag = true;
|
||||
} else {
|
||||
if (host.length === pattern.length - 1 && host === pattern.slice(1)) {
|
||||
isBypassedFlag = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (host === pattern) {
|
||||
isBypassedFlag = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
byPassedList.set(host, isBypassedFlag);
|
||||
return isBypassedFlag;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export function loadNoProxy(): string[] {
|
||||
const noProxy = getEnvironmentValue(Constants.NO_PROXY);
|
||||
if (noProxy) {
|
||||
return noProxy
|
||||
.split(",")
|
||||
.map((item) => item.trim())
|
||||
.filter((item) => item.length);
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
function extractAuthFromUrl(
|
||||
url: string
|
||||
): { username?: string; password?: string; urlWithoutAuth: string } {
|
||||
const atIndex = url.indexOf("@");
|
||||
if (atIndex === -1) {
|
||||
return { urlWithoutAuth: url };
|
||||
}
|
||||
|
||||
const schemeIndex = url.indexOf("://");
|
||||
const authStart = schemeIndex !== -1 ? schemeIndex + 3 : 0;
|
||||
const auth = url.substring(authStart, atIndex);
|
||||
const colonIndex = auth.indexOf(":");
|
||||
const hasPassword = colonIndex !== -1;
|
||||
const username = hasPassword ? auth.substring(0, colonIndex) : auth;
|
||||
const password = hasPassword ? auth.substring(colonIndex + 1) : undefined;
|
||||
const urlWithoutAuth = url.substring(0, authStart) + url.substring(atIndex + 1);
|
||||
return {
|
||||
username,
|
||||
password,
|
||||
urlWithoutAuth,
|
||||
};
|
||||
}
|
||||
|
||||
export function getDefaultProxySettings(proxyUrl?: string): ProxySettings | undefined {
|
||||
if (!proxyUrl) {
|
||||
proxyUrl = loadEnvironmentProxyValue();
|
||||
if (!proxyUrl) {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
const { username, password, urlWithoutAuth } = extractAuthFromUrl(proxyUrl);
|
||||
const parsedUrl = URLBuilder.parse(urlWithoutAuth);
|
||||
const schema = parsedUrl.getScheme() ? parsedUrl.getScheme() + "://" : "";
|
||||
return {
|
||||
host: schema + parsedUrl.getHost(),
|
||||
port: Number.parseInt(parsedUrl.getPort() || "80"),
|
||||
username,
|
||||
password,
|
||||
};
|
||||
}
|
||||
|
||||
export function proxyPolicy(proxySettings?: ProxySettings): RequestPolicyFactory {
|
||||
if (!proxySettings) {
|
||||
proxySettings = getDefaultProxySettings();
|
||||
}
|
||||
return {
|
||||
create: (nextPolicy: RequestPolicy, options: RequestPolicyOptionsLike) => {
|
||||
return new ProxyPolicy(nextPolicy, options, proxySettings!);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export class ProxyPolicy extends BaseRequestPolicy {
|
||||
proxySettings: ProxySettings;
|
||||
|
||||
constructor(
|
||||
nextPolicy: RequestPolicy,
|
||||
options: RequestPolicyOptionsLike,
|
||||
proxySettings: ProxySettings
|
||||
) {
|
||||
super(nextPolicy, options);
|
||||
this.proxySettings = proxySettings;
|
||||
}
|
||||
|
||||
public sendRequest(request: WebResourceLike): Promise<HttpOperationResponse> {
|
||||
if (!request.proxySettings && !isBypassed(request.url)) {
|
||||
request.proxySettings = this.proxySettings;
|
||||
}
|
||||
return this._nextPolicy.sendRequest(request);
|
||||
}
|
||||
}
|
105
node_modules/@azure/ms-rest-js/lib/policies/redirectPolicy.ts
generated
vendored
Normal file
105
node_modules/@azure/ms-rest-js/lib/policies/redirectPolicy.ts
generated
vendored
Normal file
|
@ -0,0 +1,105 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
import { HttpOperationResponse } from "../httpOperationResponse";
|
||||
import { URLBuilder } from "../url";
|
||||
import { WebResourceLike } from "../webResource";
|
||||
import {
|
||||
BaseRequestPolicy,
|
||||
RequestPolicy,
|
||||
RequestPolicyFactory,
|
||||
RequestPolicyOptionsLike,
|
||||
} from "./requestPolicy";
|
||||
|
||||
/**
|
||||
* Options for how redirect responses are handled.
|
||||
*/
|
||||
export interface RedirectOptions {
|
||||
/*
|
||||
* When true, redirect responses are followed. Defaults to true.
|
||||
*/
|
||||
handleRedirects: boolean;
|
||||
|
||||
/*
|
||||
* The maximum number of times the redirect URL will be tried before
|
||||
* failing. Defaults to 20.
|
||||
*/
|
||||
maxRetries?: number;
|
||||
}
|
||||
|
||||
export const DefaultRedirectOptions: RedirectOptions = {
|
||||
handleRedirects: true,
|
||||
maxRetries: 20,
|
||||
};
|
||||
|
||||
export function redirectPolicy(maximumRetries = 20): RequestPolicyFactory {
|
||||
return {
|
||||
create: (nextPolicy: RequestPolicy, options: RequestPolicyOptionsLike) => {
|
||||
return new RedirectPolicy(nextPolicy, options, maximumRetries);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export class RedirectPolicy extends BaseRequestPolicy {
|
||||
constructor(
|
||||
nextPolicy: RequestPolicy,
|
||||
options: RequestPolicyOptionsLike,
|
||||
readonly maxRetries = 20
|
||||
) {
|
||||
super(nextPolicy, options);
|
||||
}
|
||||
|
||||
public sendRequest(request: WebResourceLike): Promise<HttpOperationResponse> {
|
||||
return this._nextPolicy
|
||||
.sendRequest(request)
|
||||
.then((response) => handleRedirect(this, response, 0));
|
||||
}
|
||||
}
|
||||
|
||||
function handleRedirect(
|
||||
policy: RedirectPolicy,
|
||||
response: HttpOperationResponse,
|
||||
currentRetries: number
|
||||
): Promise<HttpOperationResponse> {
|
||||
const { request, status } = response;
|
||||
const locationHeader = response.headers.get("location");
|
||||
if (
|
||||
locationHeader &&
|
||||
(status === 300 ||
|
||||
(status === 301 && ["GET", "HEAD"].includes(request.method)) ||
|
||||
(status === 302 && ["GET", "POST", "HEAD"].includes(request.method)) ||
|
||||
(status === 303 && "POST" === request.method) ||
|
||||
status === 307) &&
|
||||
((request.redirectLimit !== undefined && currentRetries < request.redirectLimit) ||
|
||||
(request.redirectLimit === undefined && currentRetries < policy.maxRetries))
|
||||
) {
|
||||
const builder = URLBuilder.parse(request.url);
|
||||
builder.setPath(locationHeader);
|
||||
request.url = builder.toString();
|
||||
|
||||
// POST request with Status code 302 and 303 should be converted into a
|
||||
// redirected GET request if the redirect url is present in the location header
|
||||
// reference: https://tools.ietf.org/html/rfc7231#page-57 && https://fetch.spec.whatwg.org/#http-redirect-fetch
|
||||
if ((status === 302 || status === 303) && request.method === "POST") {
|
||||
request.method = "GET";
|
||||
delete request.body;
|
||||
}
|
||||
|
||||
return policy._nextPolicy
|
||||
.sendRequest(request)
|
||||
.then((res) => handleRedirect(policy, res, currentRetries + 1))
|
||||
.then((res) => recordRedirect(res, request.url));
|
||||
}
|
||||
|
||||
return Promise.resolve(response);
|
||||
}
|
||||
|
||||
function recordRedirect(response: HttpOperationResponse, redirect: string): HttpOperationResponse {
|
||||
// This is called as the recursive calls to handleRedirect() unwind,
|
||||
// only record the deepest/last redirect
|
||||
if (!response.redirected) {
|
||||
response.redirected = true;
|
||||
response.url = redirect;
|
||||
}
|
||||
return response;
|
||||
}
|
98
node_modules/@azure/ms-rest-js/lib/policies/requestPolicy.ts
generated
vendored
Normal file
98
node_modules/@azure/ms-rest-js/lib/policies/requestPolicy.ts
generated
vendored
Normal file
|
@ -0,0 +1,98 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
import { HttpOperationResponse } from "../httpOperationResponse";
|
||||
import { HttpPipelineLogger } from "../httpPipelineLogger";
|
||||
import { HttpPipelineLogLevel } from "../httpPipelineLogLevel";
|
||||
import { WebResourceLike } from "../webResource";
|
||||
|
||||
/**
|
||||
* Creates a new RequestPolicy per-request that uses the provided nextPolicy.
|
||||
*/
|
||||
export type RequestPolicyFactory = {
|
||||
create(nextPolicy: RequestPolicy, options: RequestPolicyOptionsLike): RequestPolicy;
|
||||
};
|
||||
|
||||
export interface RequestPolicy {
|
||||
sendRequest(httpRequest: WebResourceLike): Promise<HttpOperationResponse>;
|
||||
}
|
||||
|
||||
export abstract class BaseRequestPolicy implements RequestPolicy {
|
||||
protected constructor(
|
||||
readonly _nextPolicy: RequestPolicy,
|
||||
readonly _options: RequestPolicyOptionsLike
|
||||
) {}
|
||||
|
||||
public abstract sendRequest(webResource: WebResourceLike): Promise<HttpOperationResponse>;
|
||||
|
||||
/**
|
||||
* Get whether or not a log with the provided log level should be logged.
|
||||
* @param logLevel The log level of the log that will be logged.
|
||||
* @returns Whether or not a log with the provided log level should be logged.
|
||||
*/
|
||||
public shouldLog(logLevel: HttpPipelineLogLevel): boolean {
|
||||
return this._options.shouldLog(logLevel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to log the provided message to the provided logger. If no logger was provided or if
|
||||
* the log level does not meat the logger's threshold, then nothing will be logged.
|
||||
* @param logLevel The log level of this log.
|
||||
* @param message The message of this log.
|
||||
*/
|
||||
public log(logLevel: HttpPipelineLogLevel, message: string): void {
|
||||
this._options.log(logLevel, message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Optional properties that can be used when creating a RequestPolicy.
|
||||
*/
|
||||
export interface RequestPolicyOptionsLike {
|
||||
/**
|
||||
* Get whether or not a log with the provided log level should be logged.
|
||||
* @param logLevel The log level of the log that will be logged.
|
||||
* @returns Whether or not a log with the provided log level should be logged.
|
||||
*/
|
||||
shouldLog(logLevel: HttpPipelineLogLevel): boolean;
|
||||
|
||||
/**
|
||||
* Attempt to log the provided message to the provided logger. If no logger was provided or if
|
||||
* the log level does not meet the logger's threshold, then nothing will be logged.
|
||||
* @param logLevel The log level of this log.
|
||||
* @param message The message of this log.
|
||||
*/
|
||||
log(logLevel: HttpPipelineLogLevel, message: string): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Optional properties that can be used when creating a RequestPolicy.
|
||||
*/
|
||||
export class RequestPolicyOptions implements RequestPolicyOptionsLike {
|
||||
constructor(private _logger?: HttpPipelineLogger) {}
|
||||
|
||||
/**
|
||||
* Get whether or not a log with the provided log level should be logged.
|
||||
* @param logLevel The log level of the log that will be logged.
|
||||
* @returns Whether or not a log with the provided log level should be logged.
|
||||
*/
|
||||
public shouldLog(logLevel: HttpPipelineLogLevel): boolean {
|
||||
return (
|
||||
!!this._logger &&
|
||||
logLevel !== HttpPipelineLogLevel.OFF &&
|
||||
logLevel <= this._logger.minimumLogLevel
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to log the provided message to the provided logger. If no logger was provided or if
|
||||
* the log level does not meat the logger's threshold, then nothing will be logged.
|
||||
* @param logLevel The log level of this log.
|
||||
* @param message The message of this log.
|
||||
*/
|
||||
public log(logLevel: HttpPipelineLogLevel, message: string): void {
|
||||
if (this._logger && this.shouldLog(logLevel)) {
|
||||
this._logger.log(logLevel, message);
|
||||
}
|
||||
}
|
||||
}
|
197
node_modules/@azure/ms-rest-js/lib/policies/rpRegistrationPolicy.ts
generated
vendored
Normal file
197
node_modules/@azure/ms-rest-js/lib/policies/rpRegistrationPolicy.ts
generated
vendored
Normal file
|
@ -0,0 +1,197 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
import { HttpOperationResponse } from "../httpOperationResponse";
|
||||
import * as utils from "../util/utils";
|
||||
import { WebResourceLike } from "../webResource";
|
||||
import {
|
||||
BaseRequestPolicy,
|
||||
RequestPolicy,
|
||||
RequestPolicyFactory,
|
||||
RequestPolicyOptionsLike,
|
||||
} from "./requestPolicy";
|
||||
|
||||
export function rpRegistrationPolicy(retryTimeout = 30): RequestPolicyFactory {
|
||||
return {
|
||||
create: (nextPolicy: RequestPolicy, options: RequestPolicyOptionsLike) => {
|
||||
return new RPRegistrationPolicy(nextPolicy, options, retryTimeout);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export class RPRegistrationPolicy extends BaseRequestPolicy {
|
||||
constructor(
|
||||
nextPolicy: RequestPolicy,
|
||||
options: RequestPolicyOptionsLike,
|
||||
readonly _retryTimeout = 30
|
||||
) {
|
||||
super(nextPolicy, options);
|
||||
}
|
||||
|
||||
public sendRequest(request: WebResourceLike): Promise<HttpOperationResponse> {
|
||||
return this._nextPolicy
|
||||
.sendRequest(request.clone())
|
||||
.then((response) => registerIfNeeded(this, request, response));
|
||||
}
|
||||
}
|
||||
|
||||
function registerIfNeeded(
|
||||
policy: RPRegistrationPolicy,
|
||||
request: WebResourceLike,
|
||||
response: HttpOperationResponse
|
||||
): Promise<HttpOperationResponse> {
|
||||
if (response.status === 409) {
|
||||
const rpName = checkRPNotRegisteredError(response.bodyAsText as string);
|
||||
if (rpName) {
|
||||
const urlPrefix = extractSubscriptionUrl(request.url);
|
||||
return (
|
||||
registerRP(policy, urlPrefix, rpName, request)
|
||||
// Autoregistration of ${provider} failed for some reason. We will not return this error
|
||||
// instead will return the initial response with 409 status code back to the user.
|
||||
// do nothing here as we are returning the original response at the end of this method.
|
||||
.catch(() => false)
|
||||
.then((registrationStatus) => {
|
||||
if (registrationStatus) {
|
||||
// Retry the original request. We have to change the x-ms-client-request-id
|
||||
// otherwise Azure endpoint will return the initial 409 (cached) response.
|
||||
request.headers.set("x-ms-client-request-id", utils.generateUuid());
|
||||
return policy._nextPolicy.sendRequest(request.clone());
|
||||
}
|
||||
return response;
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return Promise.resolve(response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reuses the headers of the original request and url (if specified).
|
||||
* @param {WebResourceLike} originalRequest The original request
|
||||
* @param {boolean} reuseUrlToo Should the url from the original request be reused as well. Default false.
|
||||
* @returns {object} A new request object with desired headers.
|
||||
*/
|
||||
function getRequestEssentials(
|
||||
originalRequest: WebResourceLike,
|
||||
reuseUrlToo = false
|
||||
): WebResourceLike {
|
||||
const reqOptions: WebResourceLike = originalRequest.clone();
|
||||
if (reuseUrlToo) {
|
||||
reqOptions.url = originalRequest.url;
|
||||
}
|
||||
|
||||
// We have to change the x-ms-client-request-id otherwise Azure endpoint
|
||||
// will return the initial 409 (cached) response.
|
||||
reqOptions.headers.set("x-ms-client-request-id", utils.generateUuid());
|
||||
|
||||
// Set content-type to application/json
|
||||
reqOptions.headers.set("Content-Type", "application/json; charset=utf-8");
|
||||
|
||||
return reqOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the error code and message associated with 409 response status code. If it matches to that of
|
||||
* RP not registered then it returns the name of the RP else returns undefined.
|
||||
* @param {string} body The response body received after making the original request.
|
||||
* @returns {string} The name of the RP if condition is satisfied else undefined.
|
||||
*/
|
||||
function checkRPNotRegisteredError(body: string): string {
|
||||
let result, responseBody;
|
||||
if (body) {
|
||||
try {
|
||||
responseBody = JSON.parse(body);
|
||||
} catch (err) {
|
||||
// do nothing;
|
||||
}
|
||||
if (
|
||||
responseBody &&
|
||||
responseBody.error &&
|
||||
responseBody.error.message &&
|
||||
responseBody.error.code &&
|
||||
responseBody.error.code === "MissingSubscriptionRegistration"
|
||||
) {
|
||||
const matchRes = responseBody.error.message.match(/.*'(.*)'/i);
|
||||
if (matchRes) {
|
||||
result = matchRes.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the first part of the URL, just after subscription:
|
||||
* https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/
|
||||
* @param {string} url The original request url
|
||||
* @returns {string} The url prefix as explained above.
|
||||
*/
|
||||
function extractSubscriptionUrl(url: string): string {
|
||||
let result;
|
||||
const matchRes = url.match(/.*\/subscriptions\/[a-f0-9-]+\//gi);
|
||||
if (matchRes && matchRes[0]) {
|
||||
result = matchRes[0];
|
||||
} else {
|
||||
throw new Error(`Unable to extract subscriptionId from the given url - ${url}.`);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the given provider.
|
||||
* @param {RPRegistrationPolicy} policy The RPRegistrationPolicy this function is being called against.
|
||||
* @param {string} urlPrefix https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/
|
||||
* @param {string} provider The provider name to be registered.
|
||||
* @param {WebResourceLike} originalRequest The original request sent by the user that returned a 409 response
|
||||
* with a message that the provider is not registered.
|
||||
* @param {registrationCallback} callback The callback that handles the RP registration
|
||||
*/
|
||||
function registerRP(
|
||||
policy: RPRegistrationPolicy,
|
||||
urlPrefix: string,
|
||||
provider: string,
|
||||
originalRequest: WebResourceLike
|
||||
): Promise<boolean> {
|
||||
const postUrl = `${urlPrefix}providers/${provider}/register?api-version=2016-02-01`;
|
||||
const getUrl = `${urlPrefix}providers/${provider}?api-version=2016-02-01`;
|
||||
const reqOptions = getRequestEssentials(originalRequest);
|
||||
reqOptions.method = "POST";
|
||||
reqOptions.url = postUrl;
|
||||
|
||||
return policy._nextPolicy.sendRequest(reqOptions).then((response) => {
|
||||
if (response.status !== 200) {
|
||||
throw new Error(`Autoregistration of ${provider} failed. Please try registering manually.`);
|
||||
}
|
||||
return getRegistrationStatus(policy, getUrl, originalRequest);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Polls the registration status of the provider that was registered. Polling happens at an interval of 30 seconds.
|
||||
* Polling will happen till the registrationState property of the response body is "Registered".
|
||||
* @param {RPRegistrationPolicy} policy The RPRegistrationPolicy this function is being called against.
|
||||
* @param {string} url The request url for polling
|
||||
* @param {WebResourceLike} originalRequest The original request sent by the user that returned a 409 response
|
||||
* with a message that the provider is not registered.
|
||||
* @returns {Promise<boolean>} True if RP Registration is successful.
|
||||
*/
|
||||
function getRegistrationStatus(
|
||||
policy: RPRegistrationPolicy,
|
||||
url: string,
|
||||
originalRequest: WebResourceLike
|
||||
): Promise<boolean> {
|
||||
const reqOptions: any = getRequestEssentials(originalRequest);
|
||||
reqOptions.url = url;
|
||||
reqOptions.method = "GET";
|
||||
|
||||
return policy._nextPolicy.sendRequest(reqOptions).then((res) => {
|
||||
const obj = res.parsedBody as any;
|
||||
if (res.parsedBody && obj.registrationState && obj.registrationState === "Registered") {
|
||||
return true;
|
||||
} else {
|
||||
return utils
|
||||
.delay(policy._retryTimeout * 1000)
|
||||
.then(() => getRegistrationStatus(policy, url, originalRequest));
|
||||
}
|
||||
});
|
||||
}
|
42
node_modules/@azure/ms-rest-js/lib/policies/signingPolicy.ts
generated
vendored
Normal file
42
node_modules/@azure/ms-rest-js/lib/policies/signingPolicy.ts
generated
vendored
Normal file
|
@ -0,0 +1,42 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
import { ServiceClientCredentials } from "../credentials/serviceClientCredentials";
|
||||
import { HttpOperationResponse } from "../httpOperationResponse";
|
||||
import { WebResourceLike } from "../webResource";
|
||||
import {
|
||||
BaseRequestPolicy,
|
||||
RequestPolicyFactory,
|
||||
RequestPolicy,
|
||||
RequestPolicyOptionsLike,
|
||||
} from "./requestPolicy";
|
||||
|
||||
export function signingPolicy(
|
||||
authenticationProvider: ServiceClientCredentials
|
||||
): RequestPolicyFactory {
|
||||
return {
|
||||
create: (nextPolicy: RequestPolicy, options: RequestPolicyOptionsLike) => {
|
||||
return new SigningPolicy(nextPolicy, options, authenticationProvider);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export class SigningPolicy extends BaseRequestPolicy {
|
||||
constructor(
|
||||
nextPolicy: RequestPolicy,
|
||||
options: RequestPolicyOptionsLike,
|
||||
public authenticationProvider: ServiceClientCredentials
|
||||
) {
|
||||
super(nextPolicy, options);
|
||||
}
|
||||
|
||||
signRequest(request: WebResourceLike): Promise<WebResourceLike> {
|
||||
return this.authenticationProvider.signRequest(request);
|
||||
}
|
||||
|
||||
public sendRequest(request: WebResourceLike): Promise<HttpOperationResponse> {
|
||||
return this.signRequest(request).then((nextRequest) =>
|
||||
this._nextPolicy.sendRequest(nextRequest)
|
||||
);
|
||||
}
|
||||
}
|
187
node_modules/@azure/ms-rest-js/lib/policies/systemErrorRetryPolicy.ts
generated
vendored
Normal file
187
node_modules/@azure/ms-rest-js/lib/policies/systemErrorRetryPolicy.ts
generated
vendored
Normal file
|
@ -0,0 +1,187 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
import { HttpOperationResponse } from "../httpOperationResponse";
|
||||
import * as utils from "../util/utils";
|
||||
import { WebResourceLike } from "../webResource";
|
||||
import {
|
||||
BaseRequestPolicy,
|
||||
RequestPolicy,
|
||||
RequestPolicyFactory,
|
||||
RequestPolicyOptionsLike,
|
||||
} from "./requestPolicy";
|
||||
|
||||
export interface RetryData {
|
||||
retryCount: number;
|
||||
retryInterval: number;
|
||||
error?: RetryError;
|
||||
}
|
||||
|
||||
export interface RetryError extends Error {
|
||||
message: string;
|
||||
code?: string;
|
||||
innerError?: RetryError;
|
||||
}
|
||||
|
||||
export function systemErrorRetryPolicy(
|
||||
retryCount?: number,
|
||||
retryInterval?: number,
|
||||
minRetryInterval?: number,
|
||||
maxRetryInterval?: number
|
||||
): RequestPolicyFactory {
|
||||
return {
|
||||
create: (nextPolicy: RequestPolicy, options: RequestPolicyOptionsLike) => {
|
||||
return new SystemErrorRetryPolicy(
|
||||
nextPolicy,
|
||||
options,
|
||||
retryCount,
|
||||
retryInterval,
|
||||
minRetryInterval,
|
||||
maxRetryInterval
|
||||
);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @class
|
||||
* Instantiates a new "ExponentialRetryPolicyFilter" instance.
|
||||
*
|
||||
* @constructor
|
||||
* @param {number} retryCount The client retry count.
|
||||
* @param {number} retryInterval The client retry interval, in milliseconds.
|
||||
* @param {number} minRetryInterval The minimum retry interval, in milliseconds.
|
||||
* @param {number} maxRetryInterval The maximum retry interval, in milliseconds.
|
||||
*/
|
||||
export class SystemErrorRetryPolicy extends BaseRequestPolicy {
|
||||
retryCount: number;
|
||||
retryInterval: number;
|
||||
minRetryInterval: number;
|
||||
maxRetryInterval: number;
|
||||
DEFAULT_CLIENT_RETRY_INTERVAL = 1000 * 30;
|
||||
DEFAULT_CLIENT_RETRY_COUNT = 3;
|
||||
DEFAULT_CLIENT_MAX_RETRY_INTERVAL = 1000 * 90;
|
||||
DEFAULT_CLIENT_MIN_RETRY_INTERVAL = 1000 * 3;
|
||||
|
||||
constructor(
|
||||
nextPolicy: RequestPolicy,
|
||||
options: RequestPolicyOptionsLike,
|
||||
retryCount?: number,
|
||||
retryInterval?: number,
|
||||
minRetryInterval?: number,
|
||||
maxRetryInterval?: number
|
||||
) {
|
||||
super(nextPolicy, options);
|
||||
this.retryCount = typeof retryCount === "number" ? retryCount : this.DEFAULT_CLIENT_RETRY_COUNT;
|
||||
this.retryInterval =
|
||||
typeof retryInterval === "number" ? retryInterval : this.DEFAULT_CLIENT_RETRY_INTERVAL;
|
||||
this.minRetryInterval =
|
||||
typeof minRetryInterval === "number"
|
||||
? minRetryInterval
|
||||
: this.DEFAULT_CLIENT_MIN_RETRY_INTERVAL;
|
||||
this.maxRetryInterval =
|
||||
typeof maxRetryInterval === "number"
|
||||
? maxRetryInterval
|
||||
: this.DEFAULT_CLIENT_MAX_RETRY_INTERVAL;
|
||||
}
|
||||
|
||||
public sendRequest(request: WebResourceLike): Promise<HttpOperationResponse> {
|
||||
return this._nextPolicy
|
||||
.sendRequest(request.clone())
|
||||
.catch((error) => retry(this, request, error.response, error));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the operation should be retried and how long to wait until the next retry.
|
||||
*
|
||||
* @param {number} statusCode The HTTP status code.
|
||||
* @param {RetryData} retryData The retry data.
|
||||
* @return {boolean} True if the operation qualifies for a retry; false otherwise.
|
||||
*/
|
||||
function shouldRetry(policy: SystemErrorRetryPolicy, retryData: RetryData): boolean {
|
||||
let currentCount;
|
||||
if (!retryData) {
|
||||
throw new Error("retryData for the SystemErrorRetryPolicyFilter cannot be null.");
|
||||
} else {
|
||||
currentCount = retryData && retryData.retryCount;
|
||||
}
|
||||
return currentCount < policy.retryCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the retry data for the next attempt.
|
||||
*
|
||||
* @param {RetryData} retryData The retry data.
|
||||
* @param {object} err The operation"s error, if any.
|
||||
*/
|
||||
function updateRetryData(
|
||||
policy: SystemErrorRetryPolicy,
|
||||
retryData?: RetryData,
|
||||
err?: RetryError
|
||||
): RetryData {
|
||||
if (!retryData) {
|
||||
retryData = {
|
||||
retryCount: 0,
|
||||
retryInterval: 0,
|
||||
};
|
||||
}
|
||||
|
||||
if (err) {
|
||||
if (retryData.error) {
|
||||
err.innerError = retryData.error;
|
||||
}
|
||||
|
||||
retryData.error = err;
|
||||
}
|
||||
|
||||
// Adjust retry count
|
||||
retryData.retryCount++;
|
||||
|
||||
// Adjust retry interval
|
||||
let incrementDelta = Math.pow(2, retryData.retryCount) - 1;
|
||||
const boundedRandDelta =
|
||||
policy.retryInterval * 0.8 + Math.floor(Math.random() * (policy.retryInterval * 0.4));
|
||||
incrementDelta *= boundedRandDelta;
|
||||
|
||||
retryData.retryInterval = Math.min(
|
||||
policy.minRetryInterval + incrementDelta,
|
||||
policy.maxRetryInterval
|
||||
);
|
||||
|
||||
return retryData;
|
||||
}
|
||||
|
||||
async function retry(
|
||||
policy: SystemErrorRetryPolicy,
|
||||
request: WebResourceLike,
|
||||
operationResponse: HttpOperationResponse,
|
||||
err?: RetryError,
|
||||
retryData?: RetryData
|
||||
): Promise<HttpOperationResponse> {
|
||||
retryData = updateRetryData(policy, retryData, err);
|
||||
if (
|
||||
err &&
|
||||
err.code &&
|
||||
shouldRetry(policy, retryData) &&
|
||||
(err.code === "ETIMEDOUT" ||
|
||||
err.code === "ESOCKETTIMEDOUT" ||
|
||||
err.code === "ECONNREFUSED" ||
|
||||
err.code === "ECONNRESET" ||
|
||||
err.code === "ENOENT")
|
||||
) {
|
||||
// If previous operation ended with an error and the policy allows a retry, do that
|
||||
try {
|
||||
await utils.delay(retryData.retryInterval);
|
||||
return policy._nextPolicy.sendRequest(request.clone());
|
||||
} catch (error) {
|
||||
return retry(policy, request, operationResponse, error, retryData);
|
||||
}
|
||||
} else {
|
||||
if (err) {
|
||||
// If the operation failed in the end, return all errors instead of just the last one
|
||||
return Promise.reject(retryData.error);
|
||||
}
|
||||
return operationResponse;
|
||||
}
|
||||
}
|
105
node_modules/@azure/ms-rest-js/lib/policies/throttlingRetryPolicy.ts
generated
vendored
Normal file
105
node_modules/@azure/ms-rest-js/lib/policies/throttlingRetryPolicy.ts
generated
vendored
Normal file
|
@ -0,0 +1,105 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
import {
|
||||
BaseRequestPolicy,
|
||||
RequestPolicy,
|
||||
RequestPolicyOptionsLike,
|
||||
RequestPolicyFactory,
|
||||
} from "./requestPolicy";
|
||||
import { WebResourceLike } from "../webResource";
|
||||
import { HttpOperationResponse } from "../httpOperationResponse";
|
||||
import { Constants } from "../util/constants";
|
||||
import { delay } from "../util/utils";
|
||||
|
||||
const StatusCodes = Constants.HttpConstants.StatusCodes;
|
||||
const DEFAULT_RETRY_COUNT = 3;
|
||||
|
||||
/**
|
||||
* Options that control how to retry on response status code 429.
|
||||
*/
|
||||
export interface ThrottlingRetryOptions {
|
||||
/**
|
||||
* The maximum number of retry attempts. Defaults to 3.
|
||||
*/
|
||||
maxRetries?: number;
|
||||
}
|
||||
|
||||
export function throttlingRetryPolicy(
|
||||
maxRetries: number = DEFAULT_RETRY_COUNT
|
||||
): RequestPolicyFactory {
|
||||
return {
|
||||
create: (nextPolicy: RequestPolicy, options: RequestPolicyOptionsLike) => {
|
||||
return new ThrottlingRetryPolicy(nextPolicy, options, maxRetries);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* To learn more, please refer to
|
||||
* https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-manager-request-limits,
|
||||
* https://docs.microsoft.com/en-us/azure/azure-subscription-service-limits and
|
||||
* https://docs.microsoft.com/en-us/azure/virtual-machines/troubleshooting/troubleshooting-throttling-errors
|
||||
*/
|
||||
export class ThrottlingRetryPolicy extends BaseRequestPolicy {
|
||||
private retryLimit: number;
|
||||
|
||||
constructor(nextPolicy: RequestPolicy, options: RequestPolicyOptionsLike, retryLimit: number) {
|
||||
super(nextPolicy, options);
|
||||
this.retryLimit = retryLimit;
|
||||
}
|
||||
|
||||
public async sendRequest(httpRequest: WebResourceLike): Promise<HttpOperationResponse> {
|
||||
return this._nextPolicy.sendRequest(httpRequest.clone()).then((response) => {
|
||||
return this.retry(httpRequest, response, 0);
|
||||
});
|
||||
}
|
||||
|
||||
private async retry(
|
||||
httpRequest: WebResourceLike,
|
||||
httpResponse: HttpOperationResponse,
|
||||
retryCount: number
|
||||
): Promise<HttpOperationResponse> {
|
||||
if (httpResponse.status !== StatusCodes.TooManyRequests) {
|
||||
return httpResponse;
|
||||
}
|
||||
|
||||
const retryAfterHeader: string | undefined = httpResponse.headers.get(
|
||||
Constants.HeaderConstants.RETRY_AFTER
|
||||
);
|
||||
|
||||
if (retryAfterHeader && retryCount < this.retryLimit) {
|
||||
const delayInMs: number | undefined = ThrottlingRetryPolicy.parseRetryAfterHeader(
|
||||
retryAfterHeader
|
||||
);
|
||||
if (delayInMs) {
|
||||
await delay(delayInMs);
|
||||
const res = await this._nextPolicy.sendRequest(httpRequest);
|
||||
return this.retry(httpRequest, res, retryCount + 1);
|
||||
}
|
||||
}
|
||||
|
||||
return httpResponse;
|
||||
}
|
||||
|
||||
public static parseRetryAfterHeader(headerValue: string): number | undefined {
|
||||
const retryAfterInSeconds = Number(headerValue);
|
||||
if (Number.isNaN(retryAfterInSeconds)) {
|
||||
return ThrottlingRetryPolicy.parseDateRetryAfterHeader(headerValue);
|
||||
} else {
|
||||
return retryAfterInSeconds * 1000;
|
||||
}
|
||||
}
|
||||
|
||||
public static parseDateRetryAfterHeader(headerValue: string): number | undefined {
|
||||
try {
|
||||
const now: number = Date.now();
|
||||
const date: number = Date.parse(headerValue);
|
||||
const diff = date - now;
|
||||
|
||||
return Number.isNaN(diff) ? undefined : diff;
|
||||
} catch (error) {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
}
|
88
node_modules/@azure/ms-rest-js/lib/policies/userAgentPolicy.ts
generated
vendored
Normal file
88
node_modules/@azure/ms-rest-js/lib/policies/userAgentPolicy.ts
generated
vendored
Normal file
|
@ -0,0 +1,88 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
import { HttpHeaders } from "../httpHeaders";
|
||||
import { HttpOperationResponse } from "../httpOperationResponse";
|
||||
import { Constants } from "../util/constants";
|
||||
import { WebResourceLike } from "../webResource";
|
||||
import { getDefaultUserAgentKey, getPlatformSpecificData } from "./msRestUserAgentPolicy";
|
||||
import {
|
||||
BaseRequestPolicy,
|
||||
RequestPolicy,
|
||||
RequestPolicyFactory,
|
||||
RequestPolicyOptionsLike,
|
||||
} from "./requestPolicy";
|
||||
|
||||
export type TelemetryInfo = { key?: string; value?: string };
|
||||
|
||||
function getRuntimeInfo(): TelemetryInfo[] {
|
||||
const msRestRuntime = {
|
||||
key: "ms-rest-js",
|
||||
value: Constants.msRestVersion,
|
||||
};
|
||||
|
||||
return [msRestRuntime];
|
||||
}
|
||||
|
||||
function getUserAgentString(
|
||||
telemetryInfo: TelemetryInfo[],
|
||||
keySeparator = " ",
|
||||
valueSeparator = "/"
|
||||
): string {
|
||||
return telemetryInfo
|
||||
.map((info) => {
|
||||
const value = info.value ? `${valueSeparator}${info.value}` : "";
|
||||
return `${info.key}${value}`;
|
||||
})
|
||||
.join(keySeparator);
|
||||
}
|
||||
|
||||
export const getDefaultUserAgentHeaderName = getDefaultUserAgentKey;
|
||||
|
||||
export function getDefaultUserAgentValue(): string {
|
||||
const runtimeInfo = getRuntimeInfo();
|
||||
const platformSpecificData = getPlatformSpecificData();
|
||||
const userAgent = getUserAgentString(runtimeInfo.concat(platformSpecificData));
|
||||
return userAgent;
|
||||
}
|
||||
|
||||
export function userAgentPolicy(userAgentData?: TelemetryInfo): RequestPolicyFactory {
|
||||
const key: string =
|
||||
!userAgentData || userAgentData.key == undefined ? getDefaultUserAgentKey() : userAgentData.key;
|
||||
const value: string =
|
||||
!userAgentData || userAgentData.value == undefined
|
||||
? getDefaultUserAgentValue()
|
||||
: userAgentData.value;
|
||||
|
||||
return {
|
||||
create: (nextPolicy: RequestPolicy, options: RequestPolicyOptionsLike) => {
|
||||
return new UserAgentPolicy(nextPolicy, options, key, value);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export class UserAgentPolicy extends BaseRequestPolicy {
|
||||
constructor(
|
||||
readonly _nextPolicy: RequestPolicy,
|
||||
readonly _options: RequestPolicyOptionsLike,
|
||||
protected headerKey: string,
|
||||
protected headerValue: string
|
||||
) {
|
||||
super(_nextPolicy, _options);
|
||||
}
|
||||
|
||||
sendRequest(request: WebResourceLike): Promise<HttpOperationResponse> {
|
||||
this.addUserAgentHeader(request);
|
||||
return this._nextPolicy.sendRequest(request);
|
||||
}
|
||||
|
||||
addUserAgentHeader(request: WebResourceLike): void {
|
||||
if (!request.headers) {
|
||||
request.headers = new HttpHeaders();
|
||||
}
|
||||
|
||||
if (!request.headers.get(this.headerKey) && this.headerValue) {
|
||||
request.headers.set(this.headerKey, this.headerValue);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue