mirror of
https://github.com/oven-sh/setup-bun.git
synced 2025-07-18 20:48:29 +02:00
feat: add @actions/cache
This commit is contained in:
parent
b15fb7d098
commit
16e8c96a41
1932 changed files with 261172 additions and 10 deletions
25
node_modules/@azure/ms-rest-js/lib/browserFetchHttpClient.ts
generated
vendored
Normal file
25
node_modules/@azure/ms-rest-js/lib/browserFetchHttpClient.ts
generated
vendored
Normal file
|
@ -0,0 +1,25 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
import {
|
||||
CommonRequestInfo,
|
||||
CommonRequestInit,
|
||||
CommonResponse,
|
||||
FetchHttpClient,
|
||||
} from "./fetchHttpClient";
|
||||
import { HttpOperationResponse } from "./httpOperationResponse";
|
||||
import { WebResourceLike } from "./webResource";
|
||||
|
||||
export class BrowserFetchHttpClient extends FetchHttpClient {
|
||||
prepareRequest(_httpRequest: WebResourceLike): Promise<Partial<RequestInit>> {
|
||||
return Promise.resolve({});
|
||||
}
|
||||
|
||||
processRequest(_operationResponse: HttpOperationResponse): Promise<void> {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
fetch(input: CommonRequestInfo, init?: CommonRequestInit): Promise<CommonResponse> {
|
||||
return fetch(input, init);
|
||||
}
|
||||
}
|
89
node_modules/@azure/ms-rest-js/lib/credentials/apiKeyCredentials.ts
generated
vendored
Normal file
89
node_modules/@azure/ms-rest-js/lib/credentials/apiKeyCredentials.ts
generated
vendored
Normal file
|
@ -0,0 +1,89 @@
|
|||
// 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 { WebResourceLike } from "../webResource";
|
||||
import { ServiceClientCredentials } from "./serviceClientCredentials";
|
||||
|
||||
/**
|
||||
* @interface ApiKeyCredentialOptions
|
||||
* Describes the options to be provided while creating an instance of ApiKeyCredentials
|
||||
*/
|
||||
export interface ApiKeyCredentialOptions {
|
||||
/**
|
||||
* A key value pair of the header parameters that need to be applied to the request.
|
||||
*/
|
||||
inHeader?: { [x: string]: any };
|
||||
/**
|
||||
* A key value pair of the query parameters that need to be applied to the request.
|
||||
*/
|
||||
inQuery?: { [x: string]: any };
|
||||
}
|
||||
|
||||
/**
|
||||
* Authenticates to a service using an API key.
|
||||
*/
|
||||
export class ApiKeyCredentials implements ServiceClientCredentials {
|
||||
/**
|
||||
* A key value pair of the header parameters that need to be applied to the request.
|
||||
*/
|
||||
private readonly inHeader?: { [x: string]: any };
|
||||
/**
|
||||
* A key value pair of the query parameters that need to be applied to the request.
|
||||
*/
|
||||
private readonly inQuery?: { [x: string]: any };
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @param {object} options Specifies the options to be provided for auth. Either header or query needs to be provided.
|
||||
*/
|
||||
constructor(options: ApiKeyCredentialOptions) {
|
||||
if (!options || (options && !options.inHeader && !options.inQuery)) {
|
||||
throw new Error(
|
||||
`options cannot be null or undefined. Either "inHeader" or "inQuery" property of the options object needs to be provided.`
|
||||
);
|
||||
}
|
||||
this.inHeader = options.inHeader;
|
||||
this.inQuery = options.inQuery;
|
||||
}
|
||||
|
||||
/**
|
||||
* Signs a request with the values provided in the inHeader and inQuery parameter.
|
||||
*
|
||||
* @param {WebResource} webResource The WebResource to be signed.
|
||||
* @returns {Promise<WebResource>} The signed request object.
|
||||
*/
|
||||
signRequest(webResource: WebResourceLike): Promise<WebResourceLike> {
|
||||
if (!webResource) {
|
||||
return Promise.reject(
|
||||
new Error(`webResource cannot be null or undefined and must be of type "object".`)
|
||||
);
|
||||
}
|
||||
|
||||
if (this.inHeader) {
|
||||
if (!webResource.headers) {
|
||||
webResource.headers = new HttpHeaders();
|
||||
}
|
||||
for (const headerName in this.inHeader) {
|
||||
webResource.headers.set(headerName, this.inHeader[headerName]);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.inQuery) {
|
||||
if (!webResource.url) {
|
||||
return Promise.reject(new Error(`url cannot be null in the request object.`));
|
||||
}
|
||||
if (webResource.url.indexOf("?") < 0) {
|
||||
webResource.url += "?";
|
||||
}
|
||||
for (const key in this.inQuery) {
|
||||
if (!webResource.url.endsWith("?")) {
|
||||
webResource.url += "&";
|
||||
}
|
||||
webResource.url += `${key}=${this.inQuery[key]}`;
|
||||
}
|
||||
}
|
||||
|
||||
return Promise.resolve(webResource);
|
||||
}
|
||||
}
|
60
node_modules/@azure/ms-rest-js/lib/credentials/azureIdentityTokenCredentialAdapter.ts
generated
vendored
Normal file
60
node_modules/@azure/ms-rest-js/lib/credentials/azureIdentityTokenCredentialAdapter.ts
generated
vendored
Normal file
|
@ -0,0 +1,60 @@
|
|||
// 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 "./serviceClientCredentials";
|
||||
import { Constants as MSRestConstants } from "../util/constants";
|
||||
import { WebResource } from "../webResource";
|
||||
|
||||
import { TokenCredential } from "@azure/core-auth";
|
||||
import { TokenResponse } from "./tokenResponse";
|
||||
|
||||
const DEFAULT_AUTHORIZATION_SCHEME = "Bearer";
|
||||
|
||||
/**
|
||||
* Resource manager endpoints to match in order to specify a valid scope to the AzureIdentityCredentialAdapter.
|
||||
*/
|
||||
export const azureResourceManagerEndpoints = [
|
||||
"https://management.windows.net",
|
||||
"https://management.chinacloudapi.cn",
|
||||
"https://management.usgovcloudapi.net",
|
||||
"https://management.cloudapi.de",
|
||||
];
|
||||
|
||||
/**
|
||||
* This class provides a simple extension to use {@link TokenCredential} from `@azure/identity` library to
|
||||
* use with legacy Azure SDKs that accept {@link ServiceClientCredentials} family of credentials for authentication.
|
||||
*/
|
||||
export class AzureIdentityCredentialAdapter implements ServiceClientCredentials {
|
||||
private azureTokenCredential: TokenCredential;
|
||||
private scopes: string | string[];
|
||||
constructor(
|
||||
azureTokenCredential: TokenCredential,
|
||||
scopes: string | string[] = "https://management.azure.com/.default"
|
||||
) {
|
||||
this.azureTokenCredential = azureTokenCredential;
|
||||
this.scopes = scopes;
|
||||
}
|
||||
|
||||
public async getToken(): Promise<TokenResponse> {
|
||||
const accessToken = await this.azureTokenCredential.getToken(this.scopes);
|
||||
if (accessToken !== null) {
|
||||
const result: TokenResponse = {
|
||||
accessToken: accessToken.token,
|
||||
tokenType: DEFAULT_AUTHORIZATION_SCHEME,
|
||||
expiresOn: accessToken.expiresOnTimestamp,
|
||||
};
|
||||
return result;
|
||||
} else {
|
||||
throw new Error("Could find token for scope");
|
||||
}
|
||||
}
|
||||
|
||||
public async signRequest(webResource: WebResource) {
|
||||
const tokenResponse = await this.getToken();
|
||||
webResource.headers.set(
|
||||
MSRestConstants.HeaderConstants.AUTHORIZATION,
|
||||
`${tokenResponse.tokenType} ${tokenResponse.accessToken}`
|
||||
);
|
||||
return Promise.resolve(webResource);
|
||||
}
|
||||
}
|
54
node_modules/@azure/ms-rest-js/lib/credentials/basicAuthenticationCredentials.ts
generated
vendored
Normal file
54
node_modules/@azure/ms-rest-js/lib/credentials/basicAuthenticationCredentials.ts
generated
vendored
Normal file
|
@ -0,0 +1,54 @@
|
|||
// 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 * as base64 from "../util/base64";
|
||||
import { Constants } from "../util/constants";
|
||||
import { WebResourceLike } from "../webResource";
|
||||
import { ServiceClientCredentials } from "./serviceClientCredentials";
|
||||
const HeaderConstants = Constants.HeaderConstants;
|
||||
const DEFAULT_AUTHORIZATION_SCHEME = "Basic";
|
||||
|
||||
export class BasicAuthenticationCredentials implements ServiceClientCredentials {
|
||||
userName: string;
|
||||
password: string;
|
||||
authorizationScheme: string = DEFAULT_AUTHORIZATION_SCHEME;
|
||||
|
||||
/**
|
||||
* Creates a new BasicAuthenticationCredentials object.
|
||||
*
|
||||
* @constructor
|
||||
* @param {string} userName User name.
|
||||
* @param {string} password Password.
|
||||
* @param {string} [authorizationScheme] The authorization scheme.
|
||||
*/
|
||||
constructor(
|
||||
userName: string,
|
||||
password: string,
|
||||
authorizationScheme: string = DEFAULT_AUTHORIZATION_SCHEME
|
||||
) {
|
||||
if (userName === null || userName === undefined || typeof userName.valueOf() !== "string") {
|
||||
throw new Error("userName cannot be null or undefined and must be of type string.");
|
||||
}
|
||||
if (password === null || password === undefined || typeof password.valueOf() !== "string") {
|
||||
throw new Error("password cannot be null or undefined and must be of type string.");
|
||||
}
|
||||
this.userName = userName;
|
||||
this.password = password;
|
||||
this.authorizationScheme = authorizationScheme;
|
||||
}
|
||||
|
||||
/**
|
||||
* Signs a request with the Authentication header.
|
||||
*
|
||||
* @param {WebResourceLike} webResource The WebResourceLike to be signed.
|
||||
* @returns {Promise<WebResourceLike>} The signed request object.
|
||||
*/
|
||||
signRequest(webResource: WebResourceLike) {
|
||||
const credentials = `${this.userName}:${this.password}`;
|
||||
const encodedCredentials = `${this.authorizationScheme} ${base64.encodeString(credentials)}`;
|
||||
if (!webResource.headers) webResource.headers = new HttpHeaders();
|
||||
webResource.headers.set(HeaderConstants.AUTHORIZATION, encodedCredentials);
|
||||
return Promise.resolve(webResource);
|
||||
}
|
||||
}
|
4
node_modules/@azure/ms-rest-js/lib/credentials/credentials.ts
generated
vendored
Normal file
4
node_modules/@azure/ms-rest-js/lib/credentials/credentials.ts
generated
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
export type Authenticator = (challenge: object) => Promise<string>;
|
24
node_modules/@azure/ms-rest-js/lib/credentials/domainCredentials.ts
generated
vendored
Normal file
24
node_modules/@azure/ms-rest-js/lib/credentials/domainCredentials.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 { ApiKeyCredentials, ApiKeyCredentialOptions } from "./apiKeyCredentials";
|
||||
|
||||
export class DomainCredentials extends ApiKeyCredentials {
|
||||
/**
|
||||
* Creates a new EventGrid DomainCredentials object.
|
||||
*
|
||||
* @constructor
|
||||
* @param {string} domainKey The EventGrid domain key
|
||||
*/
|
||||
constructor(domainKey: string) {
|
||||
if (!domainKey || (domainKey && typeof domainKey !== "string")) {
|
||||
throw new Error("domainKey cannot be null or undefined and must be of type string.");
|
||||
}
|
||||
const options: ApiKeyCredentialOptions = {
|
||||
inHeader: {
|
||||
"aeg-sas-key": domainKey,
|
||||
},
|
||||
};
|
||||
super(options);
|
||||
}
|
||||
}
|
14
node_modules/@azure/ms-rest-js/lib/credentials/serviceClientCredentials.ts
generated
vendored
Normal file
14
node_modules/@azure/ms-rest-js/lib/credentials/serviceClientCredentials.ts
generated
vendored
Normal file
|
@ -0,0 +1,14 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
import { WebResourceLike } from "../webResource";
|
||||
|
||||
export interface ServiceClientCredentials {
|
||||
/**
|
||||
* Signs a request with the Authentication header.
|
||||
*
|
||||
* @param {WebResourceLike} webResource The WebResourceLike/request to be signed.
|
||||
* @returns {Promise<WebResourceLike>} The signed request object;
|
||||
*/
|
||||
signRequest(webResource: WebResourceLike): Promise<WebResourceLike>;
|
||||
}
|
48
node_modules/@azure/ms-rest-js/lib/credentials/tokenCredentials.ts
generated
vendored
Normal file
48
node_modules/@azure/ms-rest-js/lib/credentials/tokenCredentials.ts
generated
vendored
Normal file
|
@ -0,0 +1,48 @@
|
|||
// 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 { Constants } from "../util/constants";
|
||||
import { WebResourceLike } from "../webResource";
|
||||
import { ServiceClientCredentials } from "./serviceClientCredentials";
|
||||
|
||||
const HeaderConstants = Constants.HeaderConstants;
|
||||
const DEFAULT_AUTHORIZATION_SCHEME = "Bearer";
|
||||
|
||||
/**
|
||||
* A credentials object that uses a token string and a authorzation scheme to authenticate.
|
||||
*/
|
||||
export class TokenCredentials implements ServiceClientCredentials {
|
||||
token: string;
|
||||
authorizationScheme: string = DEFAULT_AUTHORIZATION_SCHEME;
|
||||
|
||||
/**
|
||||
* Creates a new TokenCredentials object.
|
||||
*
|
||||
* @constructor
|
||||
* @param {string} token The token.
|
||||
* @param {string} [authorizationScheme] The authorization scheme.
|
||||
*/
|
||||
constructor(token: string, authorizationScheme: string = DEFAULT_AUTHORIZATION_SCHEME) {
|
||||
if (!token) {
|
||||
throw new Error("token cannot be null or undefined.");
|
||||
}
|
||||
this.token = token;
|
||||
this.authorizationScheme = authorizationScheme;
|
||||
}
|
||||
|
||||
/**
|
||||
* Signs a request with the Authentication header.
|
||||
*
|
||||
* @param {WebResourceLike} webResource The WebResourceLike to be signed.
|
||||
* @return {Promise<WebResourceLike>} The signed request object.
|
||||
*/
|
||||
signRequest(webResource: WebResourceLike) {
|
||||
if (!webResource.headers) webResource.headers = new HttpHeaders();
|
||||
webResource.headers.set(
|
||||
HeaderConstants.AUTHORIZATION,
|
||||
`${this.authorizationScheme} ${this.token}`
|
||||
);
|
||||
return Promise.resolve(webResource);
|
||||
}
|
||||
}
|
12
node_modules/@azure/ms-rest-js/lib/credentials/tokenResponse.ts
generated
vendored
Normal file
12
node_modules/@azure/ms-rest-js/lib/credentials/tokenResponse.ts
generated
vendored
Normal file
|
@ -0,0 +1,12 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
/**
|
||||
* TokenResponse is defined in `@azure/ms-rest-nodeauth` and is copied here to not
|
||||
* add an unnecessary dependency.
|
||||
*/
|
||||
export interface TokenResponse {
|
||||
readonly tokenType: string;
|
||||
readonly accessToken: string;
|
||||
readonly [x: string]: any;
|
||||
}
|
24
node_modules/@azure/ms-rest-js/lib/credentials/topicCredentials.ts
generated
vendored
Normal file
24
node_modules/@azure/ms-rest-js/lib/credentials/topicCredentials.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 { ApiKeyCredentials, ApiKeyCredentialOptions } from "./apiKeyCredentials";
|
||||
|
||||
export class TopicCredentials extends ApiKeyCredentials {
|
||||
/**
|
||||
* Creates a new EventGrid TopicCredentials object.
|
||||
*
|
||||
* @constructor
|
||||
* @param {string} topicKey The EventGrid topic key
|
||||
*/
|
||||
constructor(topicKey: string) {
|
||||
if (!topicKey || (topicKey && typeof topicKey !== "string")) {
|
||||
throw new Error("topicKey cannot be null or undefined and must be of type string.");
|
||||
}
|
||||
const options: ApiKeyCredentialOptions = {
|
||||
inHeader: {
|
||||
"aeg-sas-key": topicKey,
|
||||
},
|
||||
};
|
||||
super(options);
|
||||
}
|
||||
}
|
4
node_modules/@azure/ms-rest-js/lib/defaultHttpClient.browser.ts
generated
vendored
Normal file
4
node_modules/@azure/ms-rest-js/lib/defaultHttpClient.browser.ts
generated
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
export { XhrHttpClient as DefaultHttpClient } from "./xhrHttpClient";
|
4
node_modules/@azure/ms-rest-js/lib/defaultHttpClient.ts
generated
vendored
Normal file
4
node_modules/@azure/ms-rest-js/lib/defaultHttpClient.ts
generated
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
export { NodeFetchHttpClient as DefaultHttpClient } from "./nodeFetchHttpClient";
|
256
node_modules/@azure/ms-rest-js/lib/fetchHttpClient.ts
generated
vendored
Normal file
256
node_modules/@azure/ms-rest-js/lib/fetchHttpClient.ts
generated
vendored
Normal file
|
@ -0,0 +1,256 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
import AbortController from "abort-controller";
|
||||
import FormData from "form-data";
|
||||
|
||||
import { HttpClient } from "./httpClient";
|
||||
import { WebResourceLike } from "./webResource";
|
||||
import { HttpOperationResponse } from "./httpOperationResponse";
|
||||
import { HttpHeaders, HttpHeadersLike } from "./httpHeaders";
|
||||
import { RestError } from "./restError";
|
||||
import { Readable, Transform } from "stream";
|
||||
|
||||
interface FetchError extends Error {
|
||||
code?: string;
|
||||
errno?: string;
|
||||
type?: string;
|
||||
}
|
||||
|
||||
export type CommonRequestInfo = string; // we only call fetch() on string urls.
|
||||
|
||||
export type CommonRequestInit = Omit<RequestInit, "body" | "headers" | "signal"> & {
|
||||
body?: any;
|
||||
headers?: any;
|
||||
signal?: any;
|
||||
};
|
||||
|
||||
export type CommonResponse = Omit<Response, "body" | "trailer" | "formData"> & {
|
||||
body: any;
|
||||
trailer: any;
|
||||
formData: any;
|
||||
};
|
||||
|
||||
export abstract class FetchHttpClient implements HttpClient {
|
||||
async sendRequest(httpRequest: WebResourceLike): Promise<HttpOperationResponse> {
|
||||
if (!httpRequest && typeof httpRequest !== "object") {
|
||||
throw new Error(
|
||||
"'httpRequest' (WebResource) cannot be null or undefined and must be of type object."
|
||||
);
|
||||
}
|
||||
|
||||
const abortController = new AbortController();
|
||||
let abortListener: ((event: any) => void) | undefined;
|
||||
if (httpRequest.abortSignal) {
|
||||
if (httpRequest.abortSignal.aborted) {
|
||||
throw new RestError(
|
||||
"The request was aborted",
|
||||
RestError.REQUEST_ABORTED_ERROR,
|
||||
undefined,
|
||||
httpRequest
|
||||
);
|
||||
}
|
||||
|
||||
abortListener = (event: Event) => {
|
||||
if (event.type === "abort") {
|
||||
abortController.abort();
|
||||
}
|
||||
};
|
||||
httpRequest.abortSignal.addEventListener("abort", abortListener);
|
||||
}
|
||||
|
||||
if (httpRequest.timeout) {
|
||||
setTimeout(() => {
|
||||
abortController.abort();
|
||||
}, httpRequest.timeout);
|
||||
}
|
||||
|
||||
if (httpRequest.formData) {
|
||||
const formData: any = httpRequest.formData;
|
||||
const requestForm = new FormData();
|
||||
const appendFormValue = (key: string, value: any) => {
|
||||
// value function probably returns a stream so we can provide a fresh stream on each retry
|
||||
if (typeof value === "function") {
|
||||
value = value();
|
||||
}
|
||||
if (value && value.hasOwnProperty("value") && value.hasOwnProperty("options")) {
|
||||
requestForm.append(key, value.value, value.options);
|
||||
} else {
|
||||
requestForm.append(key, value);
|
||||
}
|
||||
};
|
||||
for (const formKey of Object.keys(formData)) {
|
||||
const formValue = formData[formKey];
|
||||
if (Array.isArray(formValue)) {
|
||||
for (let j = 0; j < formValue.length; j++) {
|
||||
appendFormValue(formKey, formValue[j]);
|
||||
}
|
||||
} else {
|
||||
appendFormValue(formKey, formValue);
|
||||
}
|
||||
}
|
||||
|
||||
httpRequest.body = requestForm;
|
||||
httpRequest.formData = undefined;
|
||||
const contentType = httpRequest.headers.get("Content-Type");
|
||||
if (contentType && contentType.indexOf("multipart/form-data") !== -1) {
|
||||
if (typeof requestForm.getBoundary === "function") {
|
||||
httpRequest.headers.set(
|
||||
"Content-Type",
|
||||
`multipart/form-data; boundary=${requestForm.getBoundary()}`
|
||||
);
|
||||
} else {
|
||||
// browser will automatically apply a suitable content-type header
|
||||
httpRequest.headers.remove("Content-Type");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let body = httpRequest.body
|
||||
? typeof httpRequest.body === "function"
|
||||
? httpRequest.body()
|
||||
: httpRequest.body
|
||||
: undefined;
|
||||
if (httpRequest.onUploadProgress && httpRequest.body) {
|
||||
let loadedBytes = 0;
|
||||
const uploadReportStream = new Transform({
|
||||
transform: (chunk: string | Buffer, _encoding, callback) => {
|
||||
loadedBytes += chunk.length;
|
||||
httpRequest.onUploadProgress!({ loadedBytes });
|
||||
callback(undefined, chunk);
|
||||
},
|
||||
});
|
||||
|
||||
if (isReadableStream(body)) {
|
||||
body.pipe(uploadReportStream);
|
||||
} else {
|
||||
uploadReportStream.end(body);
|
||||
}
|
||||
|
||||
body = uploadReportStream;
|
||||
}
|
||||
|
||||
const platformSpecificRequestInit: Partial<RequestInit> = await this.prepareRequest(
|
||||
httpRequest
|
||||
);
|
||||
|
||||
const requestInit: RequestInit = {
|
||||
body: body,
|
||||
headers: httpRequest.headers.rawHeaders(),
|
||||
method: httpRequest.method,
|
||||
signal: abortController.signal,
|
||||
redirect: "manual",
|
||||
...platformSpecificRequestInit,
|
||||
};
|
||||
|
||||
let operationResponse: HttpOperationResponse | undefined;
|
||||
try {
|
||||
const response: CommonResponse = await this.fetch(httpRequest.url, requestInit);
|
||||
|
||||
const headers = parseHeaders(response.headers);
|
||||
operationResponse = {
|
||||
headers: headers,
|
||||
request: httpRequest,
|
||||
status: response.status,
|
||||
readableStreamBody: httpRequest.streamResponseBody
|
||||
? ((response.body as unknown) as NodeJS.ReadableStream)
|
||||
: undefined,
|
||||
bodyAsText: !httpRequest.streamResponseBody ? await response.text() : undefined,
|
||||
redirected: response.redirected,
|
||||
url: response.url,
|
||||
};
|
||||
|
||||
const onDownloadProgress = httpRequest.onDownloadProgress;
|
||||
if (onDownloadProgress) {
|
||||
const responseBody: ReadableStream<Uint8Array> | undefined = response.body || undefined;
|
||||
|
||||
if (isReadableStream(responseBody)) {
|
||||
let loadedBytes = 0;
|
||||
const downloadReportStream = new Transform({
|
||||
transform: (chunk: string | Buffer, _encoding, callback) => {
|
||||
loadedBytes += chunk.length;
|
||||
onDownloadProgress({ loadedBytes });
|
||||
callback(undefined, chunk);
|
||||
},
|
||||
});
|
||||
responseBody.pipe(downloadReportStream);
|
||||
operationResponse.readableStreamBody = downloadReportStream;
|
||||
} else {
|
||||
const length = parseInt(headers.get("Content-Length")!) || undefined;
|
||||
if (length) {
|
||||
// Calling callback for non-stream response for consistency with browser
|
||||
onDownloadProgress({ loadedBytes: length });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await this.processRequest(operationResponse);
|
||||
|
||||
return operationResponse;
|
||||
} catch (error) {
|
||||
const fetchError: FetchError = error;
|
||||
if (fetchError.code === "ENOTFOUND") {
|
||||
throw new RestError(
|
||||
fetchError.message,
|
||||
RestError.REQUEST_SEND_ERROR,
|
||||
undefined,
|
||||
httpRequest
|
||||
);
|
||||
} else if (fetchError.type === "aborted") {
|
||||
throw new RestError(
|
||||
"The request was aborted",
|
||||
RestError.REQUEST_ABORTED_ERROR,
|
||||
undefined,
|
||||
httpRequest
|
||||
);
|
||||
}
|
||||
|
||||
throw fetchError;
|
||||
} finally {
|
||||
// clean up event listener
|
||||
if (httpRequest.abortSignal && abortListener) {
|
||||
let uploadStreamDone = Promise.resolve();
|
||||
if (isReadableStream(body)) {
|
||||
uploadStreamDone = isStreamComplete(body);
|
||||
}
|
||||
let downloadStreamDone = Promise.resolve();
|
||||
if (isReadableStream(operationResponse?.readableStreamBody)) {
|
||||
downloadStreamDone = isStreamComplete(operationResponse!.readableStreamBody);
|
||||
}
|
||||
|
||||
Promise.all([uploadStreamDone, downloadStreamDone])
|
||||
.then(() => {
|
||||
httpRequest.abortSignal?.removeEventListener("abort", abortListener!);
|
||||
return;
|
||||
})
|
||||
.catch((_e) => {});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
abstract async prepareRequest(httpRequest: WebResourceLike): Promise<Partial<RequestInit>>;
|
||||
abstract async processRequest(operationResponse: HttpOperationResponse): Promise<void>;
|
||||
abstract async fetch(input: CommonRequestInfo, init?: CommonRequestInit): Promise<CommonResponse>;
|
||||
}
|
||||
|
||||
function isReadableStream(body: any): body is Readable {
|
||||
return body && typeof body.pipe === "function";
|
||||
}
|
||||
|
||||
function isStreamComplete(stream: Readable): Promise<void> {
|
||||
return new Promise((resolve) => {
|
||||
stream.on("close", resolve);
|
||||
stream.on("end", resolve);
|
||||
stream.on("error", resolve);
|
||||
});
|
||||
}
|
||||
|
||||
export function parseHeaders(headers: Headers): HttpHeadersLike {
|
||||
const httpHeaders = new HttpHeaders();
|
||||
|
||||
headers.forEach((value, key) => {
|
||||
httpHeaders.set(key, value);
|
||||
});
|
||||
|
||||
return httpHeaders;
|
||||
}
|
9
node_modules/@azure/ms-rest-js/lib/httpClient.ts
generated
vendored
Normal file
9
node_modules/@azure/ms-rest-js/lib/httpClient.ts
generated
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
import { RequestPolicy } from "./policies/requestPolicy";
|
||||
|
||||
/**
|
||||
* An interface that can send HttpRequests and receive promised HttpResponses.
|
||||
*/
|
||||
export interface HttpClient extends RequestPolicy {}
|
230
node_modules/@azure/ms-rest-js/lib/httpHeaders.ts
generated
vendored
Normal file
230
node_modules/@azure/ms-rest-js/lib/httpHeaders.ts
generated
vendored
Normal file
|
@ -0,0 +1,230 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
/**
|
||||
* A collection of HttpHeaders that can be sent with a HTTP request.
|
||||
*/
|
||||
function getHeaderKey(headerName: string) {
|
||||
return headerName.toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* An individual header within a HttpHeaders collection.
|
||||
*/
|
||||
export interface HttpHeader {
|
||||
/**
|
||||
* The name of the header.
|
||||
*/
|
||||
name: string;
|
||||
|
||||
/**
|
||||
* The value of the header.
|
||||
*/
|
||||
value: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* A HttpHeaders collection represented as a simple JSON object.
|
||||
*/
|
||||
export type RawHttpHeaders = { [headerName: string]: string };
|
||||
|
||||
/**
|
||||
* A collection of HTTP header key/value pairs.
|
||||
*/
|
||||
export interface HttpHeadersLike {
|
||||
/**
|
||||
* Set a header in this collection with the provided name and value. The name is
|
||||
* case-insensitive.
|
||||
* @param headerName The name of the header to set. This value is case-insensitive.
|
||||
* @param headerValue The value of the header to set.
|
||||
*/
|
||||
set(headerName: string, headerValue: string | number): void;
|
||||
/**
|
||||
* Get the header value for the provided header name, or undefined if no header exists in this
|
||||
* collection with the provided name.
|
||||
* @param headerName The name of the header.
|
||||
*/
|
||||
get(headerName: string): string | undefined;
|
||||
/**
|
||||
* Get whether or not this header collection contains a header entry for the provided header name.
|
||||
*/
|
||||
contains(headerName: string): boolean;
|
||||
/**
|
||||
* Remove the header with the provided headerName. Return whether or not the header existed and
|
||||
* was removed.
|
||||
* @param headerName The name of the header to remove.
|
||||
*/
|
||||
remove(headerName: string): boolean;
|
||||
/**
|
||||
* Get the headers that are contained this collection as an object.
|
||||
*/
|
||||
rawHeaders(): RawHttpHeaders;
|
||||
/**
|
||||
* Get the headers that are contained in this collection as an array.
|
||||
*/
|
||||
headersArray(): HttpHeader[];
|
||||
/**
|
||||
* Get the header names that are contained in this collection.
|
||||
*/
|
||||
headerNames(): string[];
|
||||
/**
|
||||
* Get the header values that are contained in this collection.
|
||||
*/
|
||||
headerValues(): string[];
|
||||
/**
|
||||
* Create a deep clone/copy of this HttpHeaders collection.
|
||||
*/
|
||||
clone(): HttpHeadersLike;
|
||||
/**
|
||||
* Get the JSON object representation of this HTTP header collection.
|
||||
* The result is the same as `rawHeaders()`.
|
||||
*/
|
||||
toJson(): RawHttpHeaders;
|
||||
}
|
||||
|
||||
export function isHttpHeadersLike(object?: any): object is HttpHeadersLike {
|
||||
if (!object || typeof object !== "object") {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (
|
||||
typeof object.rawHeaders === "function" &&
|
||||
typeof object.clone === "function" &&
|
||||
typeof object.get === "function" &&
|
||||
typeof object.set === "function" &&
|
||||
typeof object.contains === "function" &&
|
||||
typeof object.remove === "function" &&
|
||||
typeof object.headersArray === "function" &&
|
||||
typeof object.headerValues === "function" &&
|
||||
typeof object.headerNames === "function" &&
|
||||
typeof object.toJson === "function"
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* A collection of HTTP header key/value pairs.
|
||||
*/
|
||||
export class HttpHeaders {
|
||||
private readonly _headersMap: { [headerKey: string]: HttpHeader };
|
||||
|
||||
constructor(rawHeaders?: RawHttpHeaders) {
|
||||
this._headersMap = {};
|
||||
if (rawHeaders) {
|
||||
for (const headerName in rawHeaders) {
|
||||
this.set(headerName, rawHeaders[headerName]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a header in this collection with the provided name and value. The name is
|
||||
* case-insensitive.
|
||||
* @param headerName The name of the header to set. This value is case-insensitive.
|
||||
* @param headerValue The value of the header to set.
|
||||
*/
|
||||
public set(headerName: string, headerValue: string | number): void {
|
||||
this._headersMap[getHeaderKey(headerName)] = {
|
||||
name: headerName,
|
||||
value: headerValue.toString(),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the header value for the provided header name, or undefined if no header exists in this
|
||||
* collection with the provided name.
|
||||
* @param headerName The name of the header.
|
||||
*/
|
||||
public get(headerName: string): string | undefined {
|
||||
const header: HttpHeader = this._headersMap[getHeaderKey(headerName)];
|
||||
return !header ? undefined : header.value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get whether or not this header collection contains a header entry for the provided header name.
|
||||
*/
|
||||
public contains(headerName: string): boolean {
|
||||
return !!this._headersMap[getHeaderKey(headerName)];
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the header with the provided headerName. Return whether or not the header existed and
|
||||
* was removed.
|
||||
* @param headerName The name of the header to remove.
|
||||
*/
|
||||
public remove(headerName: string): boolean {
|
||||
const result: boolean = this.contains(headerName);
|
||||
delete this._headersMap[getHeaderKey(headerName)];
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the headers that are contained this collection as an object.
|
||||
*/
|
||||
public rawHeaders(): RawHttpHeaders {
|
||||
const result: RawHttpHeaders = {};
|
||||
for (const headerKey in this._headersMap) {
|
||||
const header: HttpHeader = this._headersMap[headerKey];
|
||||
result[header.name.toLowerCase()] = header.value;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the headers that are contained in this collection as an array.
|
||||
*/
|
||||
public headersArray(): HttpHeader[] {
|
||||
const headers: HttpHeader[] = [];
|
||||
for (const headerKey in this._headersMap) {
|
||||
headers.push(this._headersMap[headerKey]);
|
||||
}
|
||||
return headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the header names that are contained in this collection.
|
||||
*/
|
||||
public headerNames(): string[] {
|
||||
const headerNames: string[] = [];
|
||||
const headers: HttpHeader[] = this.headersArray();
|
||||
for (let i = 0; i < headers.length; ++i) {
|
||||
headerNames.push(headers[i].name);
|
||||
}
|
||||
return headerNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the header names that are contained in this collection.
|
||||
*/
|
||||
public headerValues(): string[] {
|
||||
const headerValues: string[] = [];
|
||||
const headers: HttpHeader[] = this.headersArray();
|
||||
for (let i = 0; i < headers.length; ++i) {
|
||||
headerValues.push(headers[i].value);
|
||||
}
|
||||
return headerValues;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the JSON object representation of this HTTP header collection.
|
||||
*/
|
||||
public toJson(): RawHttpHeaders {
|
||||
return this.rawHeaders();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the string representation of this HTTP header collection.
|
||||
*/
|
||||
public toString(): string {
|
||||
return JSON.stringify(this.toJson());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a deep clone/copy of this HttpHeaders collection.
|
||||
*/
|
||||
public clone(): HttpHeaders {
|
||||
return new HttpHeaders(this.rawHeaders());
|
||||
}
|
||||
}
|
94
node_modules/@azure/ms-rest-js/lib/httpOperationResponse.ts
generated
vendored
Normal file
94
node_modules/@azure/ms-rest-js/lib/httpOperationResponse.ts
generated
vendored
Normal file
|
@ -0,0 +1,94 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
import { WebResourceLike } from "./webResource";
|
||||
import { HttpHeadersLike } from "./httpHeaders";
|
||||
|
||||
/**
|
||||
* The properties on an HTTP response which will always be present.
|
||||
*/
|
||||
export interface HttpResponse {
|
||||
/**
|
||||
* The raw request
|
||||
*/
|
||||
request: WebResourceLike;
|
||||
|
||||
/**
|
||||
* The HTTP response status (e.g. 200)
|
||||
*/
|
||||
status: number;
|
||||
|
||||
/**
|
||||
* The HTTP response headers.
|
||||
*/
|
||||
headers: HttpHeadersLike;
|
||||
}
|
||||
|
||||
declare global {
|
||||
/**
|
||||
* Stub declaration of the browser-only Blob type.
|
||||
* Full type information can be obtained by including "lib": ["dom"] in tsconfig.json.
|
||||
*/
|
||||
interface Blob {}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper object for http request and response. Deserialized object is stored in
|
||||
* the `parsedBody` property when the response body is received in JSON or XML.
|
||||
*/
|
||||
export interface HttpOperationResponse extends HttpResponse {
|
||||
/**
|
||||
* The parsed HTTP response headers.
|
||||
*/
|
||||
parsedHeaders?: { [key: string]: any };
|
||||
|
||||
/**
|
||||
* The response body as text (string format)
|
||||
*/
|
||||
bodyAsText?: string | null;
|
||||
|
||||
/**
|
||||
* The response body as parsed JSON or XML
|
||||
*/
|
||||
parsedBody?: any;
|
||||
|
||||
/**
|
||||
* BROWSER ONLY
|
||||
*
|
||||
* The response body as a browser Blob.
|
||||
* Always undefined in node.js.
|
||||
*/
|
||||
blobBody?: Promise<Blob>;
|
||||
|
||||
/**
|
||||
* NODEJS ONLY
|
||||
*
|
||||
* The response body as a node.js Readable stream.
|
||||
* Always undefined in the browser.
|
||||
*/
|
||||
readableStreamBody?: NodeJS.ReadableStream;
|
||||
|
||||
/**
|
||||
* The redirected property indicates whether the response is the result of a request which was redirected.
|
||||
*/
|
||||
redirected?: boolean;
|
||||
|
||||
/**
|
||||
* The url property contains the URL of the response. The value will be the final URL obtained after any redirects.
|
||||
*/
|
||||
url?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* The flattened response to a REST call.
|
||||
* Contains the underlying HttpOperationResponse as well as
|
||||
* the merged properties of the parsedBody, parsedHeaders, etc.
|
||||
*/
|
||||
export interface RestResponse {
|
||||
/**
|
||||
* The underlying HTTP response containing both raw and deserialized response data.
|
||||
*/
|
||||
_response: HttpOperationResponse;
|
||||
|
||||
[key: string]: any;
|
||||
}
|
27
node_modules/@azure/ms-rest-js/lib/httpPipelineLogLevel.ts
generated
vendored
Normal file
27
node_modules/@azure/ms-rest-js/lib/httpPipelineLogLevel.ts
generated
vendored
Normal file
|
@ -0,0 +1,27 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
/**
|
||||
* The different levels of logs that can be used with the HttpPipelineLogger.
|
||||
*/
|
||||
export enum HttpPipelineLogLevel {
|
||||
/**
|
||||
* A log level that indicates that no logs will be logged.
|
||||
*/
|
||||
OFF,
|
||||
|
||||
/**
|
||||
* An error log.
|
||||
*/
|
||||
ERROR,
|
||||
|
||||
/**
|
||||
* A warning log.
|
||||
*/
|
||||
WARNING,
|
||||
|
||||
/**
|
||||
* An information log.
|
||||
*/
|
||||
INFO,
|
||||
}
|
55
node_modules/@azure/ms-rest-js/lib/httpPipelineLogger.ts
generated
vendored
Normal file
55
node_modules/@azure/ms-rest-js/lib/httpPipelineLogger.ts
generated
vendored
Normal file
|
@ -0,0 +1,55 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
import { HttpPipelineLogLevel } from "./httpPipelineLogLevel";
|
||||
|
||||
/**
|
||||
* A Logger that can be added to a HttpPipeline. This enables each RequestPolicy to log messages
|
||||
* that can be used for debugging purposes.
|
||||
*/
|
||||
export interface HttpPipelineLogger {
|
||||
/**
|
||||
* The log level threshold for what logs will be logged.
|
||||
*/
|
||||
minimumLogLevel: HttpPipelineLogLevel;
|
||||
|
||||
/**
|
||||
* Log the provided message.
|
||||
* @param logLevel The HttpLogDetailLevel associated with this message.
|
||||
* @param message The message to log.
|
||||
*/
|
||||
log(logLevel: HttpPipelineLogLevel, message: string): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* A HttpPipelineLogger that will send its logs to the console.
|
||||
*/
|
||||
export class ConsoleHttpPipelineLogger implements HttpPipelineLogger {
|
||||
/**
|
||||
* Create a new ConsoleHttpPipelineLogger.
|
||||
* @param minimumLogLevel The log level threshold for what logs will be logged.
|
||||
*/
|
||||
constructor(public minimumLogLevel: HttpPipelineLogLevel) {}
|
||||
|
||||
/**
|
||||
* Log the provided message.
|
||||
* @param logLevel The HttpLogDetailLevel associated with this message.
|
||||
* @param message The message to log.
|
||||
*/
|
||||
log(logLevel: HttpPipelineLogLevel, message: string): void {
|
||||
const logMessage = `${HttpPipelineLogLevel[logLevel]}: ${message}`;
|
||||
switch (logLevel) {
|
||||
case HttpPipelineLogLevel.ERROR:
|
||||
console.error(logMessage);
|
||||
break;
|
||||
|
||||
case HttpPipelineLogLevel.WARNING:
|
||||
console.warn(logMessage);
|
||||
break;
|
||||
|
||||
case HttpPipelineLogLevel.INFO:
|
||||
console.log(logMessage);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
114
node_modules/@azure/ms-rest-js/lib/msRest.ts
generated
vendored
Normal file
114
node_modules/@azure/ms-rest-js/lib/msRest.ts
generated
vendored
Normal file
|
@ -0,0 +1,114 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
/// <reference path="../dom-shim.d.ts" />
|
||||
|
||||
export {
|
||||
WebResource,
|
||||
WebResourceLike,
|
||||
HttpRequestBody,
|
||||
RequestPrepareOptions,
|
||||
HttpMethods,
|
||||
ParameterValue,
|
||||
RequestOptionsBase,
|
||||
TransferProgressEvent,
|
||||
AbortSignalLike,
|
||||
} from "./webResource";
|
||||
export { DefaultHttpClient } from "./defaultHttpClient";
|
||||
export { CommonRequestInfo, CommonRequestInit, CommonResponse } from "./fetchHttpClient";
|
||||
export { HttpClient } from "./httpClient";
|
||||
export { HttpHeader, HttpHeaders, HttpHeadersLike, RawHttpHeaders } from "./httpHeaders";
|
||||
export { HttpOperationResponse, HttpResponse, RestResponse } from "./httpOperationResponse";
|
||||
export { HttpPipelineLogger } from "./httpPipelineLogger";
|
||||
export { HttpPipelineLogLevel } from "./httpPipelineLogLevel";
|
||||
export { RestError } from "./restError";
|
||||
export { OperationArguments } from "./operationArguments";
|
||||
export {
|
||||
OperationParameter,
|
||||
OperationQueryParameter,
|
||||
OperationURLParameter,
|
||||
ParameterPath,
|
||||
} from "./operationParameter";
|
||||
export { OperationResponse } from "./operationResponse";
|
||||
export { OperationSpec } from "./operationSpec";
|
||||
export {
|
||||
AgentSettings,
|
||||
ProxySettings,
|
||||
ServiceClient,
|
||||
ServiceClientOptions,
|
||||
flattenResponse,
|
||||
} from "./serviceClient";
|
||||
export { QueryCollectionFormat } from "./queryCollectionFormat";
|
||||
export { Constants } from "./util/constants";
|
||||
export { logPolicy } from "./policies/logPolicy";
|
||||
export {
|
||||
BaseRequestPolicy,
|
||||
RequestPolicy,
|
||||
RequestPolicyFactory,
|
||||
RequestPolicyOptions,
|
||||
RequestPolicyOptionsLike,
|
||||
} from "./policies/requestPolicy";
|
||||
export { generateClientRequestIdPolicy } from "./policies/generateClientRequestIdPolicy";
|
||||
export { exponentialRetryPolicy } from "./policies/exponentialRetryPolicy";
|
||||
export { systemErrorRetryPolicy } from "./policies/systemErrorRetryPolicy";
|
||||
export { throttlingRetryPolicy } from "./policies/throttlingRetryPolicy";
|
||||
export { agentPolicy } from "./policies/agentPolicy";
|
||||
export { getDefaultProxySettings, proxyPolicy } from "./policies/proxyPolicy";
|
||||
export { RedirectOptions, redirectPolicy } from "./policies/redirectPolicy";
|
||||
export { signingPolicy } from "./policies/signingPolicy";
|
||||
export {
|
||||
TelemetryInfo,
|
||||
userAgentPolicy,
|
||||
getDefaultUserAgentValue,
|
||||
} from "./policies/userAgentPolicy";
|
||||
export {
|
||||
DeserializationContentTypes,
|
||||
deserializationPolicy,
|
||||
deserializeResponseBody,
|
||||
} from "./policies/deserializationPolicy";
|
||||
export {
|
||||
MapperType,
|
||||
SimpleMapperType,
|
||||
CompositeMapperType,
|
||||
DictionaryMapperType,
|
||||
SequenceMapperType,
|
||||
EnumMapperType,
|
||||
Mapper,
|
||||
BaseMapper,
|
||||
CompositeMapper,
|
||||
SequenceMapper,
|
||||
DictionaryMapper,
|
||||
EnumMapper,
|
||||
MapperConstraints,
|
||||
PolymorphicDiscriminator,
|
||||
Serializer,
|
||||
UrlParameterValue,
|
||||
serializeObject,
|
||||
} from "./serializer";
|
||||
export {
|
||||
stripRequest,
|
||||
stripResponse,
|
||||
delay,
|
||||
executePromisesSequentially,
|
||||
generateUuid,
|
||||
encodeUri,
|
||||
ServiceCallback,
|
||||
promiseToCallback,
|
||||
promiseToServiceCallback,
|
||||
isValidUuid,
|
||||
applyMixins,
|
||||
isNode,
|
||||
isDuration,
|
||||
} from "./util/utils";
|
||||
export { URLBuilder, URLQuery } from "./url";
|
||||
|
||||
// Credentials
|
||||
export { TokenCredentials } from "./credentials/tokenCredentials";
|
||||
export { TokenResponse } from "./credentials/tokenResponse";
|
||||
export { BasicAuthenticationCredentials } from "./credentials/basicAuthenticationCredentials";
|
||||
export { ApiKeyCredentials, ApiKeyCredentialOptions } from "./credentials/apiKeyCredentials";
|
||||
export { ServiceClientCredentials } from "./credentials/serviceClientCredentials";
|
||||
export { TopicCredentials } from "./credentials/topicCredentials";
|
||||
export { DomainCredentials } from "./credentials/domainCredentials";
|
||||
export { Authenticator } from "./credentials/credentials";
|
||||
export { AzureIdentityCredentialAdapter } from "./credentials/azureIdentityTokenCredentialAdapter";
|
95
node_modules/@azure/ms-rest-js/lib/nodeFetchHttpClient.ts
generated
vendored
Normal file
95
node_modules/@azure/ms-rest-js/lib/nodeFetchHttpClient.ts
generated
vendored
Normal file
|
@ -0,0 +1,95 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
import * as tough from "tough-cookie";
|
||||
import * as http from "http";
|
||||
import * as https from "https";
|
||||
import node_fetch from "node-fetch";
|
||||
|
||||
import {
|
||||
CommonRequestInfo,
|
||||
CommonRequestInit,
|
||||
CommonResponse,
|
||||
FetchHttpClient,
|
||||
} from "./fetchHttpClient";
|
||||
import { HttpOperationResponse } from "./httpOperationResponse";
|
||||
import { WebResourceLike } from "./webResource";
|
||||
import { createProxyAgent, ProxyAgent } from "./proxyAgent";
|
||||
|
||||
export class NodeFetchHttpClient extends FetchHttpClient {
|
||||
private readonly cookieJar = new tough.CookieJar(undefined, { looseMode: true });
|
||||
|
||||
async fetch(input: CommonRequestInfo, init?: CommonRequestInit): Promise<CommonResponse> {
|
||||
return (node_fetch(input, init) as unknown) as Promise<CommonResponse>;
|
||||
}
|
||||
|
||||
async prepareRequest(httpRequest: WebResourceLike): Promise<Partial<RequestInit>> {
|
||||
const requestInit: Partial<RequestInit & { agent?: any }> = {};
|
||||
|
||||
if (this.cookieJar && !httpRequest.headers.get("Cookie")) {
|
||||
const cookieString = await new Promise<string>((resolve, reject) => {
|
||||
this.cookieJar!.getCookieString(httpRequest.url, (err, cookie) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
resolve(cookie);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
httpRequest.headers.set("Cookie", cookieString);
|
||||
}
|
||||
|
||||
if (httpRequest.agentSettings) {
|
||||
const { http: httpAgent, https: httpsAgent } = httpRequest.agentSettings;
|
||||
if (httpsAgent && httpRequest.url.startsWith("https")) {
|
||||
requestInit.agent = httpsAgent;
|
||||
} else if (httpAgent) {
|
||||
requestInit.agent = httpAgent;
|
||||
}
|
||||
} else if (httpRequest.proxySettings) {
|
||||
const tunnel: ProxyAgent = createProxyAgent(
|
||||
httpRequest.url,
|
||||
httpRequest.proxySettings,
|
||||
httpRequest.headers
|
||||
);
|
||||
requestInit.agent = tunnel.agent;
|
||||
}
|
||||
|
||||
if (httpRequest.keepAlive === true) {
|
||||
if (requestInit.agent) {
|
||||
requestInit.agent.keepAlive = true;
|
||||
} else {
|
||||
const options: http.AgentOptions | https.AgentOptions = { keepAlive: true };
|
||||
const agent = httpRequest.url.startsWith("https")
|
||||
? new https.Agent(options)
|
||||
: new http.Agent(options);
|
||||
requestInit.agent = agent;
|
||||
}
|
||||
}
|
||||
|
||||
return requestInit;
|
||||
}
|
||||
|
||||
async processRequest(operationResponse: HttpOperationResponse): Promise<void> {
|
||||
if (this.cookieJar) {
|
||||
const setCookieHeader = operationResponse.headers.get("Set-Cookie");
|
||||
if (setCookieHeader != undefined) {
|
||||
await new Promise((resolve, reject) => {
|
||||
this.cookieJar!.setCookie(
|
||||
setCookieHeader,
|
||||
operationResponse.request.url,
|
||||
{ ignoreError: true },
|
||||
(err) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
19
node_modules/@azure/ms-rest-js/lib/operationArguments.ts
generated
vendored
Normal file
19
node_modules/@azure/ms-rest-js/lib/operationArguments.ts
generated
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
import { RequestOptionsBase } from "./webResource";
|
||||
|
||||
/**
|
||||
* A collection of properties that apply to a single invocation of an operation.
|
||||
*/
|
||||
export interface OperationArguments {
|
||||
/**
|
||||
* The parameters that were passed to the operation method.
|
||||
*/
|
||||
[parameterName: string]: any;
|
||||
|
||||
/**
|
||||
* The optional arugments that are provided to an operation.
|
||||
*/
|
||||
options?: RequestOptionsBase;
|
||||
}
|
74
node_modules/@azure/ms-rest-js/lib/operationParameter.ts
generated
vendored
Normal file
74
node_modules/@azure/ms-rest-js/lib/operationParameter.ts
generated
vendored
Normal file
|
@ -0,0 +1,74 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
import { QueryCollectionFormat } from "./queryCollectionFormat";
|
||||
import { Mapper } from "./serializer";
|
||||
|
||||
export type ParameterPath = string | string[] | { [propertyName: string]: ParameterPath };
|
||||
|
||||
/**
|
||||
* A common interface that all Operation parameter's extend.
|
||||
*/
|
||||
export interface OperationParameter {
|
||||
/**
|
||||
* The path to this parameter's value in OperationArguments or the object that contains paths for
|
||||
* each property's value in OperationArguments.
|
||||
*/
|
||||
parameterPath: ParameterPath;
|
||||
|
||||
/**
|
||||
* The mapper that defines how to validate and serialize this parameter's value.
|
||||
*/
|
||||
mapper: Mapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* A parameter for an operation that will be substituted into the operation's request URL.
|
||||
*/
|
||||
export interface OperationURLParameter extends OperationParameter {
|
||||
/**
|
||||
* Whether or not to skip encoding the URL parameter's value before adding it to the URL.
|
||||
*/
|
||||
skipEncoding?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* A parameter for an operation that will be added as a query parameter to the operation's HTTP
|
||||
* request.
|
||||
*/
|
||||
export interface OperationQueryParameter extends OperationParameter {
|
||||
/**
|
||||
* Whether or not to skip encoding the query parameter's value before adding it to the URL.
|
||||
*/
|
||||
skipEncoding?: boolean;
|
||||
|
||||
/**
|
||||
* If this query parameter's value is a collection, what type of format should the value be
|
||||
* converted to.
|
||||
*/
|
||||
collectionFormat?: QueryCollectionFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the path to this parameter's value as a dotted string (a.b.c).
|
||||
* @param parameter The parameter to get the path string for.
|
||||
* @returns The path to this parameter's value as a dotted string.
|
||||
*/
|
||||
export function getPathStringFromParameter(parameter: OperationParameter): string {
|
||||
return getPathStringFromParameterPath(parameter.parameterPath, parameter.mapper);
|
||||
}
|
||||
|
||||
export function getPathStringFromParameterPath(
|
||||
parameterPath: ParameterPath,
|
||||
mapper: Mapper
|
||||
): string {
|
||||
let result: string;
|
||||
if (typeof parameterPath === "string") {
|
||||
result = parameterPath;
|
||||
} else if (Array.isArray(parameterPath)) {
|
||||
result = parameterPath.join(".");
|
||||
} else {
|
||||
result = mapper.serializedName!;
|
||||
}
|
||||
return result;
|
||||
}
|
19
node_modules/@azure/ms-rest-js/lib/operationResponse.ts
generated
vendored
Normal file
19
node_modules/@azure/ms-rest-js/lib/operationResponse.ts
generated
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
import { Mapper } from "./serializer";
|
||||
|
||||
/**
|
||||
* An OperationResponse that can be returned from an operation request for a single status code.
|
||||
*/
|
||||
export interface OperationResponse {
|
||||
/**
|
||||
* The mapper that will be used to deserialize the response headers.
|
||||
*/
|
||||
headersMapper?: Mapper;
|
||||
|
||||
/**
|
||||
* The mapper that will be used to deserialize the response body.
|
||||
*/
|
||||
bodyMapper?: Mapper;
|
||||
}
|
98
node_modules/@azure/ms-rest-js/lib/operationSpec.ts
generated
vendored
Normal file
98
node_modules/@azure/ms-rest-js/lib/operationSpec.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 {
|
||||
OperationParameter,
|
||||
OperationQueryParameter,
|
||||
OperationURLParameter,
|
||||
} from "./operationParameter";
|
||||
import { OperationResponse } from "./operationResponse";
|
||||
import { MapperType, Serializer } from "./serializer";
|
||||
import { HttpMethods } from "./webResource";
|
||||
|
||||
/**
|
||||
* A specification that defines an operation.
|
||||
*/
|
||||
export interface OperationSpec {
|
||||
/**
|
||||
* The serializer to use in this operation.
|
||||
*/
|
||||
readonly serializer: Serializer;
|
||||
|
||||
/**
|
||||
* The HTTP method that should be used by requests for this operation.
|
||||
*/
|
||||
readonly httpMethod: HttpMethods;
|
||||
|
||||
/**
|
||||
* The URL that was provided in the service's specification. This will still have all of the URL
|
||||
* template variables in it. If this is not provided when the OperationSpec is created, then it
|
||||
* will be populated by a "baseUri" property on the ServiceClient.
|
||||
*/
|
||||
readonly baseUrl?: string;
|
||||
|
||||
/**
|
||||
* The fixed path for this operation's URL. This will still have all of the URL template variables
|
||||
* in it.
|
||||
*/
|
||||
readonly path?: string;
|
||||
|
||||
/**
|
||||
* The content type of the request body. This value will be used as the "Content-Type" header if
|
||||
* it is provided.
|
||||
*/
|
||||
readonly contentType?: string;
|
||||
|
||||
/**
|
||||
* The parameter that will be used to construct the HTTP request's body.
|
||||
*/
|
||||
readonly requestBody?: OperationParameter;
|
||||
|
||||
/**
|
||||
* Whether or not this operation uses XML request and response bodies.
|
||||
*/
|
||||
readonly isXML?: boolean;
|
||||
|
||||
/**
|
||||
* The parameters to the operation method that will be substituted into the constructed URL.
|
||||
*/
|
||||
readonly urlParameters?: ReadonlyArray<OperationURLParameter>;
|
||||
|
||||
/**
|
||||
* The parameters to the operation method that will be added to the constructed URL's query.
|
||||
*/
|
||||
readonly queryParameters?: ReadonlyArray<OperationQueryParameter>;
|
||||
|
||||
/**
|
||||
* The parameters to the operation method that will be converted to headers on the operation's
|
||||
* HTTP request.
|
||||
*/
|
||||
readonly headerParameters?: ReadonlyArray<OperationParameter>;
|
||||
|
||||
/**
|
||||
* The parameters to the operation method that will be used to create a formdata body for the
|
||||
* operation's HTTP request.
|
||||
*/
|
||||
readonly formDataParameters?: ReadonlyArray<OperationParameter>;
|
||||
|
||||
/**
|
||||
* The different types of responses that this operation can return based on what status code is
|
||||
* returned.
|
||||
*/
|
||||
readonly responses: { [responseCode: string]: OperationResponse };
|
||||
}
|
||||
|
||||
export function isStreamOperation(operationSpec: OperationSpec): boolean {
|
||||
let result = false;
|
||||
for (const statusCode in operationSpec.responses) {
|
||||
const operationResponse: OperationResponse = operationSpec.responses[statusCode];
|
||||
if (
|
||||
operationResponse.bodyMapper &&
|
||||
operationResponse.bodyMapper.type.name === MapperType.Stream
|
||||
) {
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
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);
|
||||
}
|
||||
}
|
||||
}
|
81
node_modules/@azure/ms-rest-js/lib/proxyAgent.ts
generated
vendored
Normal file
81
node_modules/@azure/ms-rest-js/lib/proxyAgent.ts
generated
vendored
Normal file
|
@ -0,0 +1,81 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
import * as http from "http";
|
||||
import * as https from "https";
|
||||
import * as tunnel from "tunnel";
|
||||
|
||||
import { ProxySettings } from "./serviceClient";
|
||||
import { URLBuilder } from "./url";
|
||||
import { HttpHeadersLike } from "./httpHeaders";
|
||||
|
||||
export type ProxyAgent = { isHttps: boolean; agent: http.Agent | https.Agent };
|
||||
export function createProxyAgent(
|
||||
requestUrl: string,
|
||||
proxySettings: ProxySettings,
|
||||
headers?: HttpHeadersLike
|
||||
): ProxyAgent {
|
||||
const tunnelOptions: tunnel.HttpsOverHttpsOptions = {
|
||||
proxy: {
|
||||
host: URLBuilder.parse(proxySettings.host).getHost() as string,
|
||||
port: proxySettings.port,
|
||||
headers: (headers && headers.rawHeaders()) || {},
|
||||
},
|
||||
};
|
||||
|
||||
if (proxySettings.username && proxySettings.password) {
|
||||
tunnelOptions.proxy!.proxyAuth = `${proxySettings.username}:${proxySettings.password}`;
|
||||
} else if (proxySettings.username) {
|
||||
tunnelOptions.proxy!.proxyAuth = `${proxySettings.username}`;
|
||||
}
|
||||
|
||||
const requestScheme = URLBuilder.parse(requestUrl).getScheme() || "";
|
||||
const isRequestHttps = requestScheme.toLowerCase() === "https";
|
||||
const proxyScheme = URLBuilder.parse(proxySettings.host).getScheme() || "";
|
||||
const isProxyHttps = proxyScheme.toLowerCase() === "https";
|
||||
|
||||
const proxyAgent = {
|
||||
isHttps: isRequestHttps,
|
||||
agent: createTunnel(isRequestHttps, isProxyHttps, tunnelOptions),
|
||||
};
|
||||
|
||||
return proxyAgent;
|
||||
}
|
||||
|
||||
// Duplicate tunnel.HttpsOverHttpsOptions to avoid exporting createTunnel() with dependency on @types/tunnel
|
||||
// createIunnel() is only imported by tests.
|
||||
export interface HttpsProxyOptions {
|
||||
host: string;
|
||||
port: number;
|
||||
localAddress?: string;
|
||||
proxyAuth?: string;
|
||||
headers?: { [key: string]: any };
|
||||
ca?: Buffer[];
|
||||
servername?: string;
|
||||
key?: Buffer;
|
||||
cert?: Buffer;
|
||||
}
|
||||
|
||||
interface HttpsOverHttpsOptions {
|
||||
maxSockets?: number;
|
||||
ca?: Buffer[];
|
||||
key?: Buffer;
|
||||
cert?: Buffer;
|
||||
proxy?: HttpsProxyOptions;
|
||||
}
|
||||
|
||||
export function createTunnel(
|
||||
isRequestHttps: boolean,
|
||||
isProxyHttps: boolean,
|
||||
tunnelOptions: HttpsOverHttpsOptions
|
||||
): http.Agent | https.Agent {
|
||||
if (isRequestHttps && isProxyHttps) {
|
||||
return tunnel.httpsOverHttps(tunnelOptions);
|
||||
} else if (isRequestHttps && !isProxyHttps) {
|
||||
return tunnel.httpsOverHttp(tunnelOptions);
|
||||
} else if (!isRequestHttps && isProxyHttps) {
|
||||
return tunnel.httpOverHttps(tunnelOptions);
|
||||
} else {
|
||||
return tunnel.httpOverHttp(tunnelOptions);
|
||||
}
|
||||
}
|
13
node_modules/@azure/ms-rest-js/lib/queryCollectionFormat.ts
generated
vendored
Normal file
13
node_modules/@azure/ms-rest-js/lib/queryCollectionFormat.ts
generated
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
/**
|
||||
* The format that will be used to join an array of values together for a query parameter value.
|
||||
*/
|
||||
export enum QueryCollectionFormat {
|
||||
Csv = ",",
|
||||
Ssv = " ",
|
||||
Tsv = "\t",
|
||||
Pipes = "|",
|
||||
Multi = "Multi",
|
||||
}
|
34
node_modules/@azure/ms-rest-js/lib/restError.ts
generated
vendored
Normal file
34
node_modules/@azure/ms-rest-js/lib/restError.ts
generated
vendored
Normal file
|
@ -0,0 +1,34 @@
|
|||
// 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";
|
||||
|
||||
export class RestError extends Error {
|
||||
static readonly REQUEST_SEND_ERROR: string = "REQUEST_SEND_ERROR";
|
||||
static readonly REQUEST_ABORTED_ERROR: string = "REQUEST_ABORTED_ERROR";
|
||||
static readonly PARSE_ERROR: string = "PARSE_ERROR";
|
||||
|
||||
code?: string;
|
||||
statusCode?: number;
|
||||
request?: WebResourceLike;
|
||||
response?: HttpOperationResponse;
|
||||
body?: any;
|
||||
constructor(
|
||||
message: string,
|
||||
code?: string,
|
||||
statusCode?: number,
|
||||
request?: WebResourceLike,
|
||||
response?: HttpOperationResponse,
|
||||
body?: any
|
||||
) {
|
||||
super(message);
|
||||
this.code = code;
|
||||
this.statusCode = statusCode;
|
||||
this.request = request;
|
||||
this.response = response;
|
||||
this.body = body;
|
||||
|
||||
Object.setPrototypeOf(this, RestError.prototype);
|
||||
}
|
||||
}
|
1063
node_modules/@azure/ms-rest-js/lib/serializer.ts
generated
vendored
Normal file
1063
node_modules/@azure/ms-rest-js/lib/serializer.ts
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
852
node_modules/@azure/ms-rest-js/lib/serviceClient.ts
generated
vendored
Normal file
852
node_modules/@azure/ms-rest-js/lib/serviceClient.ts
generated
vendored
Normal file
|
@ -0,0 +1,852 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
import { TokenCredential, isTokenCredential } from "@azure/core-auth";
|
||||
import { ServiceClientCredentials } from "./credentials/serviceClientCredentials";
|
||||
import { DefaultHttpClient } from "./defaultHttpClient";
|
||||
import { HttpClient } from "./httpClient";
|
||||
import { HttpOperationResponse, RestResponse } from "./httpOperationResponse";
|
||||
import { HttpPipelineLogger } from "./httpPipelineLogger";
|
||||
import { OperationArguments } from "./operationArguments";
|
||||
import {
|
||||
getPathStringFromParameter,
|
||||
getPathStringFromParameterPath,
|
||||
OperationParameter,
|
||||
ParameterPath,
|
||||
} from "./operationParameter";
|
||||
import { isStreamOperation, OperationSpec } from "./operationSpec";
|
||||
import {
|
||||
deserializationPolicy,
|
||||
DeserializationContentTypes,
|
||||
} from "./policies/deserializationPolicy";
|
||||
import { exponentialRetryPolicy } from "./policies/exponentialRetryPolicy";
|
||||
import { generateClientRequestIdPolicy } from "./policies/generateClientRequestIdPolicy";
|
||||
import {
|
||||
userAgentPolicy,
|
||||
getDefaultUserAgentHeaderName,
|
||||
getDefaultUserAgentValue,
|
||||
} from "./policies/userAgentPolicy";
|
||||
import { DefaultRedirectOptions, RedirectOptions, redirectPolicy } from "./policies/redirectPolicy";
|
||||
import {
|
||||
RequestPolicy,
|
||||
RequestPolicyFactory,
|
||||
RequestPolicyOptions,
|
||||
RequestPolicyOptionsLike,
|
||||
} from "./policies/requestPolicy";
|
||||
import { rpRegistrationPolicy } from "./policies/rpRegistrationPolicy";
|
||||
import { signingPolicy } from "./policies/signingPolicy";
|
||||
import { systemErrorRetryPolicy } from "./policies/systemErrorRetryPolicy";
|
||||
import { QueryCollectionFormat } from "./queryCollectionFormat";
|
||||
import { CompositeMapper, DictionaryMapper, Mapper, MapperType, Serializer } from "./serializer";
|
||||
import { URLBuilder } from "./url";
|
||||
import * as utils from "./util/utils";
|
||||
import { stringifyXML } from "./util/xml";
|
||||
import {
|
||||
RequestOptionsBase,
|
||||
RequestPrepareOptions,
|
||||
WebResourceLike,
|
||||
isWebResourceLike,
|
||||
WebResource,
|
||||
} from "./webResource";
|
||||
import { OperationResponse } from "./operationResponse";
|
||||
import { ServiceCallback } from "./util/utils";
|
||||
import { agentPolicy } from "./policies/agentPolicy";
|
||||
import { proxyPolicy, getDefaultProxySettings } from "./policies/proxyPolicy";
|
||||
import { throttlingRetryPolicy } from "./policies/throttlingRetryPolicy";
|
||||
import { Agent } from "http";
|
||||
import {
|
||||
AzureIdentityCredentialAdapter,
|
||||
azureResourceManagerEndpoints,
|
||||
} from "./credentials/azureIdentityTokenCredentialAdapter";
|
||||
|
||||
/**
|
||||
* HTTP proxy settings (Node.js only)
|
||||
*/
|
||||
export interface ProxySettings {
|
||||
host: string;
|
||||
port: number;
|
||||
username?: string;
|
||||
password?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* HTTP and HTTPS agents (Node.js only)
|
||||
*/
|
||||
export interface AgentSettings {
|
||||
http: Agent;
|
||||
https: Agent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Options to be provided while creating the client.
|
||||
*/
|
||||
export interface ServiceClientOptions {
|
||||
/**
|
||||
* An array of factories which get called to create the RequestPolicy pipeline used to send a HTTP
|
||||
* request on the wire, or a function that takes in the defaultRequestPolicyFactories and returns
|
||||
* the requestPolicyFactories that will be used.
|
||||
*/
|
||||
requestPolicyFactories?:
|
||||
| RequestPolicyFactory[]
|
||||
| ((defaultRequestPolicyFactories: RequestPolicyFactory[]) => void | RequestPolicyFactory[]);
|
||||
/**
|
||||
* The HttpClient that will be used to send HTTP requests.
|
||||
*/
|
||||
httpClient?: HttpClient;
|
||||
/**
|
||||
* The HttpPipelineLogger that can be used to debug RequestPolicies within the HTTP pipeline.
|
||||
*/
|
||||
httpPipelineLogger?: HttpPipelineLogger;
|
||||
/**
|
||||
* If set to true, turn off the default retry policy.
|
||||
*/
|
||||
noRetryPolicy?: boolean;
|
||||
/**
|
||||
* Gets or sets the retry timeout in seconds for AutomaticRPRegistration. Default value is 30.
|
||||
*/
|
||||
rpRegistrationRetryTimeout?: number;
|
||||
/**
|
||||
* Whether or not to generate a client request ID header for each HTTP request.
|
||||
*/
|
||||
generateClientRequestIdHeader?: boolean;
|
||||
/**
|
||||
* Whether to include credentials in CORS requests in the browser.
|
||||
* See https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/withCredentials for more information.
|
||||
*/
|
||||
withCredentials?: boolean;
|
||||
/**
|
||||
* If specified, a GenerateRequestIdPolicy will be added to the HTTP pipeline that will add a
|
||||
* header to all outgoing requests with this header name and a random UUID as the request ID.
|
||||
*/
|
||||
clientRequestIdHeaderName?: string;
|
||||
/**
|
||||
* The content-types that will be associated with JSON or XML serialization.
|
||||
*/
|
||||
deserializationContentTypes?: DeserializationContentTypes;
|
||||
/**
|
||||
* The header name to use for the telemetry header while sending the request. If this is not
|
||||
* specified, then "User-Agent" will be used when running on Node.js and "x-ms-command-name" will
|
||||
* be used when running in a browser.
|
||||
*/
|
||||
userAgentHeaderName?: string | ((defaultUserAgentHeaderName: string) => string);
|
||||
/**
|
||||
* The string to be set to the telemetry header while sending the request, or a function that
|
||||
* takes in the default user-agent string and returns the user-agent string that will be used.
|
||||
*/
|
||||
userAgent?: string | ((defaultUserAgent: string) => string);
|
||||
/**
|
||||
* Proxy settings which will be used for every HTTP request (Node.js only).
|
||||
*/
|
||||
proxySettings?: ProxySettings;
|
||||
/**
|
||||
* Options for how redirect responses are handled.
|
||||
*/
|
||||
redirectOptions?: RedirectOptions;
|
||||
/**
|
||||
* HTTP and HTTPS agents which will be used for every HTTP request (Node.js only).
|
||||
*/
|
||||
agentSettings?: AgentSettings;
|
||||
/**
|
||||
* If specified:
|
||||
* - This `baseUri` becomes the base URI that requests will be made against for this ServiceClient.
|
||||
* - If the `baseUri` matches a known resource manager endpoint and if a `TokenCredential` was passed through the constructor, this `baseUri` defines the `getToken` scope to be `${options.baseUri}/.default`. Otherwise, the scope would default to "https://management.azure.com/.default".
|
||||
*
|
||||
* If it is not specified:
|
||||
* - All OperationSpecs must contain a baseUrl property.
|
||||
* - If a `TokenCredential` was passed through the constructor, the `getToken` scope is set to be "https://management.azure.com/.default".
|
||||
*/
|
||||
baseUri?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* @class
|
||||
* Initializes a new instance of the ServiceClient.
|
||||
*/
|
||||
export class ServiceClient {
|
||||
/**
|
||||
* The base URI against which requests will be made when using this ServiceClient instance.
|
||||
*
|
||||
* This can be set either by setting the `baseUri` in the `options` parameter to the ServiceClient constructor or directly after constructing the ServiceClient.
|
||||
* If set via the ServiceClient constructor when using the overload that takes the `TokenCredential`, and if it matches a known resource manager endpoint, this base URI sets the scope used to get the AAD token to `${baseUri}/.default` instead of the default "https://management.azure.com/.default"
|
||||
*
|
||||
* If it is not specified, all OperationSpecs must contain a baseUrl property.
|
||||
*/
|
||||
protected baseUri?: string;
|
||||
|
||||
/**
|
||||
* The default request content type for the service.
|
||||
* Used if no requestContentType is present on an OperationSpec.
|
||||
*/
|
||||
protected requestContentType?: string;
|
||||
|
||||
/**
|
||||
* The HTTP client that will be used to send requests.
|
||||
*/
|
||||
private readonly _httpClient: HttpClient;
|
||||
private readonly _requestPolicyOptions: RequestPolicyOptionsLike;
|
||||
|
||||
private readonly _requestPolicyFactories: RequestPolicyFactory[];
|
||||
private readonly _withCredentials: boolean;
|
||||
|
||||
/**
|
||||
* The ServiceClient constructor
|
||||
* @constructor
|
||||
* @param {ServiceClientCredentials} [credentials] The credentials object used for authentication.
|
||||
* @param {ServiceClientOptions} [options] The service client options that govern the behavior of the client.
|
||||
*/
|
||||
constructor(
|
||||
credentials?: ServiceClientCredentials | TokenCredential,
|
||||
options?: ServiceClientOptions
|
||||
) {
|
||||
if (!options) {
|
||||
options = {};
|
||||
}
|
||||
|
||||
if (options.baseUri) {
|
||||
this.baseUri = options.baseUri;
|
||||
}
|
||||
|
||||
let serviceClientCredentials: ServiceClientCredentials | undefined;
|
||||
if (isTokenCredential(credentials)) {
|
||||
let scope: string | undefined = undefined;
|
||||
if (options?.baseUri && azureResourceManagerEndpoints.includes(options?.baseUri)) {
|
||||
scope = `${options.baseUri}/.default`;
|
||||
}
|
||||
serviceClientCredentials = new AzureIdentityCredentialAdapter(credentials, scope);
|
||||
} else {
|
||||
serviceClientCredentials = credentials;
|
||||
}
|
||||
|
||||
if (serviceClientCredentials && !serviceClientCredentials.signRequest) {
|
||||
throw new Error("credentials argument needs to implement signRequest method");
|
||||
}
|
||||
|
||||
this._withCredentials = options.withCredentials || false;
|
||||
this._httpClient = options.httpClient || new DefaultHttpClient();
|
||||
this._requestPolicyOptions = new RequestPolicyOptions(options.httpPipelineLogger);
|
||||
|
||||
let requestPolicyFactories: RequestPolicyFactory[];
|
||||
if (Array.isArray(options.requestPolicyFactories)) {
|
||||
requestPolicyFactories = options.requestPolicyFactories;
|
||||
} else {
|
||||
requestPolicyFactories = createDefaultRequestPolicyFactories(
|
||||
serviceClientCredentials,
|
||||
options
|
||||
);
|
||||
if (options.requestPolicyFactories) {
|
||||
const newRequestPolicyFactories:
|
||||
| void
|
||||
| RequestPolicyFactory[] = options.requestPolicyFactories(requestPolicyFactories);
|
||||
if (newRequestPolicyFactories) {
|
||||
requestPolicyFactories = newRequestPolicyFactories;
|
||||
}
|
||||
}
|
||||
}
|
||||
this._requestPolicyFactories = requestPolicyFactories;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the provided httpRequest.
|
||||
*/
|
||||
sendRequest(options: RequestPrepareOptions | WebResourceLike): Promise<HttpOperationResponse> {
|
||||
if (options === null || options === undefined || typeof options !== "object") {
|
||||
throw new Error("options cannot be null or undefined and it must be of type object.");
|
||||
}
|
||||
|
||||
let httpRequest: WebResourceLike;
|
||||
try {
|
||||
if (isWebResourceLike(options)) {
|
||||
options.validateRequestProperties();
|
||||
httpRequest = options;
|
||||
} else {
|
||||
httpRequest = new WebResource();
|
||||
httpRequest = httpRequest.prepare(options);
|
||||
}
|
||||
} catch (error) {
|
||||
return Promise.reject(error);
|
||||
}
|
||||
|
||||
let httpPipeline: RequestPolicy = this._httpClient;
|
||||
if (this._requestPolicyFactories && this._requestPolicyFactories.length > 0) {
|
||||
for (let i = this._requestPolicyFactories.length - 1; i >= 0; --i) {
|
||||
httpPipeline = this._requestPolicyFactories[i].create(
|
||||
httpPipeline,
|
||||
this._requestPolicyOptions
|
||||
);
|
||||
}
|
||||
}
|
||||
return httpPipeline.sendRequest(httpRequest);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an HTTP request that is populated using the provided OperationSpec.
|
||||
* @param {OperationArguments} operationArguments The arguments that the HTTP request's templated values will be populated from.
|
||||
* @param {OperationSpec} operationSpec The OperationSpec to use to populate the httpRequest.
|
||||
* @param {ServiceCallback} callback The callback to call when the response is received.
|
||||
*/
|
||||
sendOperationRequest(
|
||||
operationArguments: OperationArguments,
|
||||
operationSpec: OperationSpec,
|
||||
callback?: ServiceCallback<any>
|
||||
): Promise<RestResponse> {
|
||||
if (typeof operationArguments.options === "function") {
|
||||
callback = operationArguments.options;
|
||||
operationArguments.options = undefined;
|
||||
}
|
||||
|
||||
const httpRequest = new WebResource();
|
||||
|
||||
let result: Promise<RestResponse>;
|
||||
try {
|
||||
const baseUri: string | undefined = operationSpec.baseUrl || this.baseUri;
|
||||
if (!baseUri) {
|
||||
throw new Error(
|
||||
"If operationSpec.baseUrl is not specified, then the ServiceClient must have a baseUri string property that contains the base URL to use."
|
||||
);
|
||||
}
|
||||
|
||||
httpRequest.method = operationSpec.httpMethod;
|
||||
httpRequest.operationSpec = operationSpec;
|
||||
|
||||
const requestUrl: URLBuilder = URLBuilder.parse(baseUri);
|
||||
if (operationSpec.path) {
|
||||
requestUrl.appendPath(operationSpec.path);
|
||||
}
|
||||
if (operationSpec.urlParameters && operationSpec.urlParameters.length > 0) {
|
||||
for (const urlParameter of operationSpec.urlParameters) {
|
||||
let urlParameterValue: string = getOperationArgumentValueFromParameter(
|
||||
this,
|
||||
operationArguments,
|
||||
urlParameter,
|
||||
operationSpec.serializer
|
||||
);
|
||||
urlParameterValue = operationSpec.serializer.serialize(
|
||||
urlParameter.mapper,
|
||||
urlParameterValue,
|
||||
getPathStringFromParameter(urlParameter)
|
||||
);
|
||||
if (!urlParameter.skipEncoding) {
|
||||
urlParameterValue = encodeURIComponent(urlParameterValue);
|
||||
}
|
||||
requestUrl.replaceAll(
|
||||
`{${urlParameter.mapper.serializedName || getPathStringFromParameter(urlParameter)}}`,
|
||||
urlParameterValue
|
||||
);
|
||||
}
|
||||
}
|
||||
if (operationSpec.queryParameters && operationSpec.queryParameters.length > 0) {
|
||||
for (const queryParameter of operationSpec.queryParameters) {
|
||||
let queryParameterValue: any = getOperationArgumentValueFromParameter(
|
||||
this,
|
||||
operationArguments,
|
||||
queryParameter,
|
||||
operationSpec.serializer
|
||||
);
|
||||
if (queryParameterValue != undefined) {
|
||||
queryParameterValue = operationSpec.serializer.serialize(
|
||||
queryParameter.mapper,
|
||||
queryParameterValue,
|
||||
getPathStringFromParameter(queryParameter)
|
||||
);
|
||||
if (queryParameter.collectionFormat != undefined) {
|
||||
if (queryParameter.collectionFormat === QueryCollectionFormat.Multi) {
|
||||
if (queryParameterValue.length === 0) {
|
||||
queryParameterValue = "";
|
||||
} else {
|
||||
for (const index in queryParameterValue) {
|
||||
const item = queryParameterValue[index];
|
||||
queryParameterValue[index] = item == undefined ? "" : item.toString();
|
||||
}
|
||||
}
|
||||
} else if (
|
||||
queryParameter.collectionFormat === QueryCollectionFormat.Ssv ||
|
||||
queryParameter.collectionFormat === QueryCollectionFormat.Tsv
|
||||
) {
|
||||
queryParameterValue = queryParameterValue.join(queryParameter.collectionFormat);
|
||||
}
|
||||
}
|
||||
if (!queryParameter.skipEncoding) {
|
||||
if (Array.isArray(queryParameterValue)) {
|
||||
for (const index in queryParameterValue) {
|
||||
if (
|
||||
queryParameterValue[index] !== undefined &&
|
||||
queryParameterValue[index] !== null
|
||||
) {
|
||||
queryParameterValue[index] = encodeURIComponent(queryParameterValue[index]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
queryParameterValue = encodeURIComponent(queryParameterValue);
|
||||
}
|
||||
}
|
||||
if (
|
||||
queryParameter.collectionFormat != undefined &&
|
||||
queryParameter.collectionFormat !== QueryCollectionFormat.Multi &&
|
||||
queryParameter.collectionFormat !== QueryCollectionFormat.Ssv &&
|
||||
queryParameter.collectionFormat !== QueryCollectionFormat.Tsv
|
||||
) {
|
||||
queryParameterValue = queryParameterValue.join(queryParameter.collectionFormat);
|
||||
}
|
||||
requestUrl.setQueryParameter(
|
||||
queryParameter.mapper.serializedName || getPathStringFromParameter(queryParameter),
|
||||
queryParameterValue
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
httpRequest.url = requestUrl.toString();
|
||||
|
||||
const contentType = operationSpec.contentType || this.requestContentType;
|
||||
if (contentType) {
|
||||
httpRequest.headers.set("Content-Type", contentType);
|
||||
}
|
||||
|
||||
if (operationSpec.headerParameters) {
|
||||
for (const headerParameter of operationSpec.headerParameters) {
|
||||
let headerValue: any = getOperationArgumentValueFromParameter(
|
||||
this,
|
||||
operationArguments,
|
||||
headerParameter,
|
||||
operationSpec.serializer
|
||||
);
|
||||
if (headerValue != undefined) {
|
||||
headerValue = operationSpec.serializer.serialize(
|
||||
headerParameter.mapper,
|
||||
headerValue,
|
||||
getPathStringFromParameter(headerParameter)
|
||||
);
|
||||
const headerCollectionPrefix = (headerParameter.mapper as DictionaryMapper)
|
||||
.headerCollectionPrefix;
|
||||
if (headerCollectionPrefix) {
|
||||
for (const key of Object.keys(headerValue)) {
|
||||
httpRequest.headers.set(headerCollectionPrefix + key, headerValue[key]);
|
||||
}
|
||||
} else {
|
||||
httpRequest.headers.set(
|
||||
headerParameter.mapper.serializedName ||
|
||||
getPathStringFromParameter(headerParameter),
|
||||
headerValue
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const options: RequestOptionsBase | undefined = operationArguments.options;
|
||||
if (options) {
|
||||
if (options.customHeaders) {
|
||||
for (const customHeaderName in options.customHeaders) {
|
||||
httpRequest.headers.set(customHeaderName, options.customHeaders[customHeaderName]);
|
||||
}
|
||||
}
|
||||
|
||||
if (options.abortSignal) {
|
||||
httpRequest.abortSignal = options.abortSignal;
|
||||
}
|
||||
|
||||
if (options.timeout) {
|
||||
httpRequest.timeout = options.timeout;
|
||||
}
|
||||
|
||||
if (options.onUploadProgress) {
|
||||
httpRequest.onUploadProgress = options.onUploadProgress;
|
||||
}
|
||||
|
||||
if (options.onDownloadProgress) {
|
||||
httpRequest.onDownloadProgress = options.onDownloadProgress;
|
||||
}
|
||||
}
|
||||
|
||||
httpRequest.withCredentials = this._withCredentials;
|
||||
|
||||
serializeRequestBody(this, httpRequest, operationArguments, operationSpec);
|
||||
|
||||
if (httpRequest.streamResponseBody == undefined) {
|
||||
httpRequest.streamResponseBody = isStreamOperation(operationSpec);
|
||||
}
|
||||
|
||||
result = this.sendRequest(httpRequest).then((res) =>
|
||||
flattenResponse(res, operationSpec.responses[res.status])
|
||||
);
|
||||
} catch (error) {
|
||||
result = Promise.reject(error);
|
||||
}
|
||||
|
||||
const cb = callback;
|
||||
if (cb) {
|
||||
result
|
||||
// tslint:disable-next-line:no-null-keyword
|
||||
.then((res) => cb(null, res._response.parsedBody, res._response.request, res._response))
|
||||
.catch((err) => cb(err));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
export function serializeRequestBody(
|
||||
serviceClient: ServiceClient,
|
||||
httpRequest: WebResourceLike,
|
||||
operationArguments: OperationArguments,
|
||||
operationSpec: OperationSpec
|
||||
): void {
|
||||
if (operationSpec.requestBody && operationSpec.requestBody.mapper) {
|
||||
httpRequest.body = getOperationArgumentValueFromParameter(
|
||||
serviceClient,
|
||||
operationArguments,
|
||||
operationSpec.requestBody,
|
||||
operationSpec.serializer
|
||||
);
|
||||
|
||||
const bodyMapper = operationSpec.requestBody.mapper;
|
||||
const { required, xmlName, xmlElementName, serializedName } = bodyMapper;
|
||||
const typeName = bodyMapper.type.name;
|
||||
try {
|
||||
if (httpRequest.body != undefined || required) {
|
||||
const requestBodyParameterPathString: string = getPathStringFromParameter(
|
||||
operationSpec.requestBody
|
||||
);
|
||||
httpRequest.body = operationSpec.serializer.serialize(
|
||||
bodyMapper,
|
||||
httpRequest.body,
|
||||
requestBodyParameterPathString
|
||||
);
|
||||
const isStream = typeName === MapperType.Stream;
|
||||
if (operationSpec.isXML) {
|
||||
if (typeName === MapperType.Sequence) {
|
||||
httpRequest.body = stringifyXML(
|
||||
utils.prepareXMLRootList(
|
||||
httpRequest.body,
|
||||
xmlElementName || xmlName || serializedName!
|
||||
),
|
||||
{ rootName: xmlName || serializedName }
|
||||
);
|
||||
} else if (!isStream) {
|
||||
httpRequest.body = stringifyXML(httpRequest.body, {
|
||||
rootName: xmlName || serializedName,
|
||||
});
|
||||
}
|
||||
} else if (!isStream) {
|
||||
httpRequest.body = JSON.stringify(httpRequest.body);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
throw new Error(
|
||||
`Error "${error.message}" occurred in serializing the payload - ${JSON.stringify(
|
||||
serializedName,
|
||||
undefined,
|
||||
" "
|
||||
)}.`
|
||||
);
|
||||
}
|
||||
} else if (operationSpec.formDataParameters && operationSpec.formDataParameters.length > 0) {
|
||||
httpRequest.formData = {};
|
||||
for (const formDataParameter of operationSpec.formDataParameters) {
|
||||
const formDataParameterValue: any = getOperationArgumentValueFromParameter(
|
||||
serviceClient,
|
||||
operationArguments,
|
||||
formDataParameter,
|
||||
operationSpec.serializer
|
||||
);
|
||||
if (formDataParameterValue != undefined) {
|
||||
const formDataParameterPropertyName: string =
|
||||
formDataParameter.mapper.serializedName || getPathStringFromParameter(formDataParameter);
|
||||
httpRequest.formData[formDataParameterPropertyName] = operationSpec.serializer.serialize(
|
||||
formDataParameter.mapper,
|
||||
formDataParameterValue,
|
||||
getPathStringFromParameter(formDataParameter)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function isRequestPolicyFactory(instance: any): instance is RequestPolicyFactory {
|
||||
return typeof instance.create === "function";
|
||||
}
|
||||
|
||||
function getValueOrFunctionResult(
|
||||
value: undefined | string | ((defaultValue: string) => string),
|
||||
defaultValueCreator: () => string
|
||||
): string {
|
||||
let result: string;
|
||||
if (typeof value === "string") {
|
||||
result = value;
|
||||
} else {
|
||||
result = defaultValueCreator();
|
||||
if (typeof value === "function") {
|
||||
result = value(result);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function createDefaultRequestPolicyFactories(
|
||||
credentials: ServiceClientCredentials | RequestPolicyFactory | undefined,
|
||||
options: ServiceClientOptions
|
||||
): RequestPolicyFactory[] {
|
||||
const factories: RequestPolicyFactory[] = [];
|
||||
|
||||
if (options.generateClientRequestIdHeader) {
|
||||
factories.push(generateClientRequestIdPolicy(options.clientRequestIdHeaderName));
|
||||
}
|
||||
|
||||
if (credentials) {
|
||||
if (isRequestPolicyFactory(credentials)) {
|
||||
factories.push(credentials);
|
||||
} else {
|
||||
factories.push(signingPolicy(credentials));
|
||||
}
|
||||
}
|
||||
|
||||
const userAgentHeaderName: string = getValueOrFunctionResult(
|
||||
options.userAgentHeaderName,
|
||||
getDefaultUserAgentHeaderName
|
||||
);
|
||||
const userAgentHeaderValue: string = getValueOrFunctionResult(
|
||||
options.userAgent,
|
||||
getDefaultUserAgentValue
|
||||
);
|
||||
if (userAgentHeaderName && userAgentHeaderValue) {
|
||||
factories.push(userAgentPolicy({ key: userAgentHeaderName, value: userAgentHeaderValue }));
|
||||
}
|
||||
|
||||
const redirectOptions = {
|
||||
...DefaultRedirectOptions,
|
||||
...options.redirectOptions,
|
||||
};
|
||||
if (redirectOptions.handleRedirects) {
|
||||
factories.push(redirectPolicy(redirectOptions.maxRetries));
|
||||
}
|
||||
|
||||
factories.push(rpRegistrationPolicy(options.rpRegistrationRetryTimeout));
|
||||
|
||||
if (!options.noRetryPolicy) {
|
||||
factories.push(exponentialRetryPolicy());
|
||||
factories.push(systemErrorRetryPolicy());
|
||||
factories.push(throttlingRetryPolicy());
|
||||
}
|
||||
|
||||
factories.push(deserializationPolicy(options.deserializationContentTypes));
|
||||
|
||||
const proxySettings = options.proxySettings || getDefaultProxySettings();
|
||||
if (proxySettings) {
|
||||
factories.push(proxyPolicy(proxySettings));
|
||||
}
|
||||
|
||||
if (options.agentSettings) {
|
||||
factories.push(agentPolicy(options.agentSettings));
|
||||
}
|
||||
|
||||
return factories;
|
||||
}
|
||||
|
||||
export type PropertyParent = { [propertyName: string]: any };
|
||||
|
||||
/**
|
||||
* Get the property parent for the property at the provided path when starting with the provided
|
||||
* parent object.
|
||||
*/
|
||||
export function getPropertyParent(parent: PropertyParent, propertyPath: string[]): PropertyParent {
|
||||
if (parent && propertyPath) {
|
||||
const propertyPathLength: number = propertyPath.length;
|
||||
for (let i = 0; i < propertyPathLength - 1; ++i) {
|
||||
const propertyName: string = propertyPath[i];
|
||||
if (!parent[propertyName]) {
|
||||
parent[propertyName] = {};
|
||||
}
|
||||
parent = parent[propertyName];
|
||||
}
|
||||
}
|
||||
return parent;
|
||||
}
|
||||
|
||||
function getOperationArgumentValueFromParameter(
|
||||
serviceClient: ServiceClient,
|
||||
operationArguments: OperationArguments,
|
||||
parameter: OperationParameter,
|
||||
serializer: Serializer
|
||||
): any {
|
||||
return getOperationArgumentValueFromParameterPath(
|
||||
serviceClient,
|
||||
operationArguments,
|
||||
parameter.parameterPath,
|
||||
parameter.mapper,
|
||||
serializer
|
||||
);
|
||||
}
|
||||
|
||||
export function getOperationArgumentValueFromParameterPath(
|
||||
serviceClient: ServiceClient,
|
||||
operationArguments: OperationArguments,
|
||||
parameterPath: ParameterPath,
|
||||
parameterMapper: Mapper,
|
||||
serializer: Serializer
|
||||
): any {
|
||||
let value: any;
|
||||
if (typeof parameterPath === "string") {
|
||||
parameterPath = [parameterPath];
|
||||
}
|
||||
if (Array.isArray(parameterPath)) {
|
||||
if (parameterPath.length > 0) {
|
||||
if (parameterMapper.isConstant) {
|
||||
value = parameterMapper.defaultValue;
|
||||
} else {
|
||||
let propertySearchResult: PropertySearchResult = getPropertyFromParameterPath(
|
||||
operationArguments,
|
||||
parameterPath
|
||||
);
|
||||
if (!propertySearchResult.propertyFound) {
|
||||
propertySearchResult = getPropertyFromParameterPath(serviceClient, parameterPath);
|
||||
}
|
||||
|
||||
let useDefaultValue = false;
|
||||
if (!propertySearchResult.propertyFound) {
|
||||
useDefaultValue =
|
||||
parameterMapper.required ||
|
||||
(parameterPath[0] === "options" && parameterPath.length === 2);
|
||||
}
|
||||
value = useDefaultValue ? parameterMapper.defaultValue : propertySearchResult.propertyValue;
|
||||
}
|
||||
|
||||
// Serialize just for validation purposes.
|
||||
const parameterPathString: string = getPathStringFromParameterPath(
|
||||
parameterPath,
|
||||
parameterMapper
|
||||
);
|
||||
serializer.serialize(parameterMapper, value, parameterPathString);
|
||||
}
|
||||
} else {
|
||||
if (parameterMapper.required) {
|
||||
value = {};
|
||||
}
|
||||
|
||||
for (const propertyName in parameterPath) {
|
||||
const propertyMapper: Mapper = (parameterMapper as CompositeMapper).type.modelProperties![
|
||||
propertyName
|
||||
];
|
||||
const propertyPath: ParameterPath = parameterPath[propertyName];
|
||||
const propertyValue: any = getOperationArgumentValueFromParameterPath(
|
||||
serviceClient,
|
||||
operationArguments,
|
||||
propertyPath,
|
||||
propertyMapper,
|
||||
serializer
|
||||
);
|
||||
// Serialize just for validation purposes.
|
||||
const propertyPathString: string = getPathStringFromParameterPath(
|
||||
propertyPath,
|
||||
propertyMapper
|
||||
);
|
||||
serializer.serialize(propertyMapper, propertyValue, propertyPathString);
|
||||
if (propertyValue !== undefined) {
|
||||
if (!value) {
|
||||
value = {};
|
||||
}
|
||||
value[propertyName] = propertyValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
interface PropertySearchResult {
|
||||
propertyValue?: any;
|
||||
propertyFound: boolean;
|
||||
}
|
||||
|
||||
function getPropertyFromParameterPath(
|
||||
parent: { [parameterName: string]: any },
|
||||
parameterPath: string[]
|
||||
): PropertySearchResult {
|
||||
const result: PropertySearchResult = { propertyFound: false };
|
||||
let i = 0;
|
||||
for (; i < parameterPath.length; ++i) {
|
||||
const parameterPathPart: string = parameterPath[i];
|
||||
// Make sure to check inherited properties too, so don't use hasOwnProperty().
|
||||
if (parent != undefined && parameterPathPart in parent) {
|
||||
parent = parent[parameterPathPart];
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i === parameterPath.length) {
|
||||
result.propertyValue = parent;
|
||||
result.propertyFound = true;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function flattenResponse(
|
||||
_response: HttpOperationResponse,
|
||||
responseSpec: OperationResponse | undefined
|
||||
): RestResponse {
|
||||
const parsedHeaders = _response.parsedHeaders;
|
||||
const bodyMapper = responseSpec && responseSpec.bodyMapper;
|
||||
|
||||
const addOperationResponse = (obj: {}) =>
|
||||
Object.defineProperty(obj, "_response", {
|
||||
value: _response,
|
||||
});
|
||||
|
||||
if (bodyMapper) {
|
||||
const typeName = bodyMapper.type.name;
|
||||
if (typeName === "Stream") {
|
||||
return addOperationResponse({
|
||||
...parsedHeaders,
|
||||
blobBody: _response.blobBody,
|
||||
readableStreamBody: _response.readableStreamBody,
|
||||
});
|
||||
}
|
||||
|
||||
const modelProperties =
|
||||
(typeName === "Composite" && (bodyMapper as CompositeMapper).type.modelProperties) || {};
|
||||
const isPageableResponse = Object.keys(modelProperties).some(
|
||||
(k) => modelProperties[k].serializedName === ""
|
||||
);
|
||||
if (typeName === "Sequence" || isPageableResponse) {
|
||||
// We're expecting a sequece(array) make sure that the response body is in the
|
||||
// correct format, if not make it an empty array []
|
||||
const parsedBody = Array.isArray(_response.parsedBody) ? _response.parsedBody : [];
|
||||
const arrayResponse = [...parsedBody] as RestResponse & any[];
|
||||
|
||||
for (const key of Object.keys(modelProperties)) {
|
||||
if (modelProperties[key].serializedName) {
|
||||
arrayResponse[key] = _response.parsedBody[key];
|
||||
}
|
||||
}
|
||||
|
||||
if (parsedHeaders) {
|
||||
for (const key of Object.keys(parsedHeaders)) {
|
||||
arrayResponse[key] = parsedHeaders[key];
|
||||
}
|
||||
}
|
||||
addOperationResponse(arrayResponse);
|
||||
return arrayResponse;
|
||||
}
|
||||
|
||||
if (typeName === "Composite" || typeName === "Dictionary") {
|
||||
return addOperationResponse({
|
||||
...parsedHeaders,
|
||||
..._response.parsedBody,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
bodyMapper ||
|
||||
_response.request.method === "HEAD" ||
|
||||
utils.isPrimitiveType(_response.parsedBody)
|
||||
) {
|
||||
// primitive body types and HEAD booleans
|
||||
return addOperationResponse({
|
||||
...parsedHeaders,
|
||||
body: _response.parsedBody,
|
||||
});
|
||||
}
|
||||
|
||||
return addOperationResponse({
|
||||
...parsedHeaders,
|
||||
..._response.parsedBody,
|
||||
});
|
||||
}
|
659
node_modules/@azure/ms-rest-js/lib/url.ts
generated
vendored
Normal file
659
node_modules/@azure/ms-rest-js/lib/url.ts
generated
vendored
Normal file
|
@ -0,0 +1,659 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
import { replaceAll } from "./util/utils";
|
||||
|
||||
type URLQueryParseState = "ParameterName" | "ParameterValue" | "Invalid";
|
||||
|
||||
/**
|
||||
* A class that handles the query portion of a URLBuilder.
|
||||
*/
|
||||
export class URLQuery {
|
||||
private readonly _rawQuery: { [queryParameterName: string]: string | string[] } = {};
|
||||
|
||||
/**
|
||||
* Get whether or not there any query parameters in this URLQuery.
|
||||
*/
|
||||
public any(): boolean {
|
||||
return Object.keys(this._rawQuery).length > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a query parameter with the provided name and value. If the parameterValue is undefined or
|
||||
* empty, then this will attempt to remove an existing query parameter with the provided
|
||||
* parameterName.
|
||||
*/
|
||||
public set(parameterName: string, parameterValue: any): void {
|
||||
if (parameterName) {
|
||||
if (parameterValue != undefined) {
|
||||
const newValue = Array.isArray(parameterValue) ? parameterValue : parameterValue.toString();
|
||||
this._rawQuery[parameterName] = newValue;
|
||||
} else {
|
||||
delete this._rawQuery[parameterName];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of the query parameter with the provided name. If no parameter exists with the
|
||||
* provided parameter name, then undefined will be returned.
|
||||
*/
|
||||
public get(parameterName: string): string | string[] | undefined {
|
||||
return parameterName ? this._rawQuery[parameterName] : undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the string representation of this query. The return value will not start with a "?".
|
||||
*/
|
||||
public toString(): string {
|
||||
let result = "";
|
||||
for (const parameterName in this._rawQuery) {
|
||||
if (result) {
|
||||
result += "&";
|
||||
}
|
||||
const parameterValue = this._rawQuery[parameterName];
|
||||
if (Array.isArray(parameterValue)) {
|
||||
const parameterStrings = [];
|
||||
for (const parameterValueElement of parameterValue) {
|
||||
parameterStrings.push(`${parameterName}=${parameterValueElement}`);
|
||||
}
|
||||
result += parameterStrings.join("&");
|
||||
} else {
|
||||
result += `${parameterName}=${parameterValue}`;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a URLQuery from the provided text.
|
||||
*/
|
||||
public static parse(text: string): URLQuery {
|
||||
const result = new URLQuery();
|
||||
|
||||
if (text) {
|
||||
if (text.startsWith("?")) {
|
||||
text = text.substring(1);
|
||||
}
|
||||
|
||||
let currentState: URLQueryParseState = "ParameterName";
|
||||
|
||||
let parameterName = "";
|
||||
let parameterValue = "";
|
||||
for (let i = 0; i < text.length; ++i) {
|
||||
const currentCharacter: string = text[i];
|
||||
switch (currentState) {
|
||||
case "ParameterName":
|
||||
switch (currentCharacter) {
|
||||
case "=":
|
||||
currentState = "ParameterValue";
|
||||
break;
|
||||
|
||||
case "&":
|
||||
parameterName = "";
|
||||
parameterValue = "";
|
||||
break;
|
||||
|
||||
default:
|
||||
parameterName += currentCharacter;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case "ParameterValue":
|
||||
switch (currentCharacter) {
|
||||
case "&":
|
||||
result.set(parameterName, parameterValue);
|
||||
parameterName = "";
|
||||
parameterValue = "";
|
||||
currentState = "ParameterName";
|
||||
break;
|
||||
|
||||
default:
|
||||
parameterValue += currentCharacter;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Error("Unrecognized URLQuery parse state: " + currentState);
|
||||
}
|
||||
}
|
||||
if (currentState === "ParameterValue") {
|
||||
result.set(parameterName, parameterValue);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A class that handles creating, modifying, and parsing URLs.
|
||||
*/
|
||||
export class URLBuilder {
|
||||
private _scheme: string | undefined;
|
||||
private _host: string | undefined;
|
||||
private _port: string | undefined;
|
||||
private _path: string | undefined;
|
||||
private _query: URLQuery | undefined;
|
||||
|
||||
/**
|
||||
* Set the scheme/protocol for this URL. If the provided scheme contains other parts of a URL
|
||||
* (such as a host, port, path, or query), those parts will be added to this URL as well.
|
||||
*/
|
||||
public setScheme(scheme: string | undefined): void {
|
||||
if (!scheme) {
|
||||
this._scheme = undefined;
|
||||
} else {
|
||||
this.set(scheme, "SCHEME");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the scheme that has been set in this URL.
|
||||
*/
|
||||
public getScheme(): string | undefined {
|
||||
return this._scheme;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the host for this URL. If the provided host contains other parts of a URL (such as a
|
||||
* port, path, or query), those parts will be added to this URL as well.
|
||||
*/
|
||||
public setHost(host: string | undefined): void {
|
||||
if (!host) {
|
||||
this._host = undefined;
|
||||
} else {
|
||||
this.set(host, "SCHEME_OR_HOST");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the host that has been set in this URL.
|
||||
*/
|
||||
public getHost(): string | undefined {
|
||||
return this._host;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the port for this URL. If the provided port contains other parts of a URL (such as a
|
||||
* path or query), those parts will be added to this URL as well.
|
||||
*/
|
||||
public setPort(port: number | string | undefined): void {
|
||||
if (port == undefined || port === "") {
|
||||
this._port = undefined;
|
||||
} else {
|
||||
this.set(port.toString(), "PORT");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the port that has been set in this URL.
|
||||
*/
|
||||
public getPort(): string | undefined {
|
||||
return this._port;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the path for this URL. If the provided path contains a query, then it will be added to
|
||||
* this URL as well.
|
||||
*/
|
||||
public setPath(path: string | undefined): void {
|
||||
if (!path) {
|
||||
this._path = undefined;
|
||||
} else {
|
||||
const schemeIndex = path.indexOf("://");
|
||||
if (schemeIndex !== -1) {
|
||||
const schemeStart = path.lastIndexOf("/", schemeIndex);
|
||||
// Make sure to only grab the URL part of the path before setting the state back to SCHEME
|
||||
// this will handle cases such as "/a/b/c/https://microsoft.com" => "https://microsoft.com"
|
||||
this.set(schemeStart === -1 ? path : path.substr(schemeStart + 1), "SCHEME");
|
||||
} else {
|
||||
this.set(path, "PATH");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Append the provided path to this URL's existing path. If the provided path contains a query,
|
||||
* then it will be added to this URL as well.
|
||||
*/
|
||||
public appendPath(path: string | undefined): void {
|
||||
if (path) {
|
||||
let currentPath: string | undefined = this.getPath();
|
||||
if (currentPath) {
|
||||
if (!currentPath.endsWith("/")) {
|
||||
currentPath += "/";
|
||||
}
|
||||
|
||||
if (path.startsWith("/")) {
|
||||
path = path.substring(1);
|
||||
}
|
||||
|
||||
path = currentPath + path;
|
||||
}
|
||||
this.set(path, "PATH");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the path that has been set in this URL.
|
||||
*/
|
||||
public getPath(): string | undefined {
|
||||
return this._path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the query in this URL.
|
||||
*/
|
||||
public setQuery(query: string | undefined): void {
|
||||
if (!query) {
|
||||
this._query = undefined;
|
||||
} else {
|
||||
this._query = URLQuery.parse(query);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a query parameter with the provided name and value in this URL's query. If the provided
|
||||
* query parameter value is undefined or empty, then the query parameter will be removed if it
|
||||
* existed.
|
||||
*/
|
||||
public setQueryParameter(queryParameterName: string, queryParameterValue: any): void {
|
||||
if (queryParameterName) {
|
||||
if (!this._query) {
|
||||
this._query = new URLQuery();
|
||||
}
|
||||
this._query.set(queryParameterName, queryParameterValue);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of the query parameter with the provided query parameter name. If no query
|
||||
* parameter exists with the provided name, then undefined will be returned.
|
||||
*/
|
||||
public getQueryParameterValue(queryParameterName: string): string | string[] | undefined {
|
||||
return this._query ? this._query.get(queryParameterName) : undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the query in this URL.
|
||||
*/
|
||||
public getQuery(): string | undefined {
|
||||
return this._query ? this._query.toString() : undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the parts of this URL by parsing the provided text using the provided startState.
|
||||
*/
|
||||
private set(text: string, startState: URLTokenizerState): void {
|
||||
const tokenizer = new URLTokenizer(text, startState);
|
||||
|
||||
while (tokenizer.next()) {
|
||||
const token: URLToken | undefined = tokenizer.current();
|
||||
if (token) {
|
||||
switch (token.type) {
|
||||
case "SCHEME":
|
||||
this._scheme = token.text || undefined;
|
||||
break;
|
||||
|
||||
case "HOST":
|
||||
this._host = token.text || undefined;
|
||||
break;
|
||||
|
||||
case "PORT":
|
||||
this._port = token.text || undefined;
|
||||
break;
|
||||
|
||||
case "PATH":
|
||||
const tokenPath: string | undefined = token.text || undefined;
|
||||
if (!this._path || this._path === "/" || tokenPath !== "/") {
|
||||
this._path = tokenPath;
|
||||
}
|
||||
break;
|
||||
|
||||
case "QUERY":
|
||||
this._query = URLQuery.parse(token.text);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Error(`Unrecognized URLTokenType: ${token.type}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public toString(): string {
|
||||
let result = "";
|
||||
|
||||
if (this._scheme) {
|
||||
result += `${this._scheme}://`;
|
||||
}
|
||||
|
||||
if (this._host) {
|
||||
result += this._host;
|
||||
}
|
||||
|
||||
if (this._port) {
|
||||
result += `:${this._port}`;
|
||||
}
|
||||
|
||||
if (this._path) {
|
||||
if (!this._path.startsWith("/")) {
|
||||
result += "/";
|
||||
}
|
||||
result += this._path;
|
||||
}
|
||||
|
||||
if (this._query && this._query.any()) {
|
||||
result += `?${this._query.toString()}`;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the provided searchValue is found in this URLBuilder, then replace it with the provided
|
||||
* replaceValue.
|
||||
*/
|
||||
public replaceAll(searchValue: string, replaceValue: string): void {
|
||||
if (searchValue) {
|
||||
this.setScheme(replaceAll(this.getScheme(), searchValue, replaceValue));
|
||||
this.setHost(replaceAll(this.getHost(), searchValue, replaceValue));
|
||||
this.setPort(replaceAll(this.getPort(), searchValue, replaceValue));
|
||||
this.setPath(replaceAll(this.getPath(), searchValue, replaceValue));
|
||||
this.setQuery(replaceAll(this.getQuery(), searchValue, replaceValue));
|
||||
}
|
||||
}
|
||||
|
||||
public static parse(text: string): URLBuilder {
|
||||
const result = new URLBuilder();
|
||||
result.set(text, "SCHEME_OR_HOST");
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
type URLTokenizerState = "SCHEME" | "SCHEME_OR_HOST" | "HOST" | "PORT" | "PATH" | "QUERY" | "DONE";
|
||||
|
||||
type URLTokenType = "SCHEME" | "HOST" | "PORT" | "PATH" | "QUERY";
|
||||
|
||||
export class URLToken {
|
||||
public constructor(public readonly text: string, public readonly type: URLTokenType) {}
|
||||
|
||||
public static scheme(text: string): URLToken {
|
||||
return new URLToken(text, "SCHEME");
|
||||
}
|
||||
|
||||
public static host(text: string): URLToken {
|
||||
return new URLToken(text, "HOST");
|
||||
}
|
||||
|
||||
public static port(text: string): URLToken {
|
||||
return new URLToken(text, "PORT");
|
||||
}
|
||||
|
||||
public static path(text: string): URLToken {
|
||||
return new URLToken(text, "PATH");
|
||||
}
|
||||
|
||||
public static query(text: string): URLToken {
|
||||
return new URLToken(text, "QUERY");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get whether or not the provided character (single character string) is an alphanumeric (letter or
|
||||
* digit) character.
|
||||
*/
|
||||
export function isAlphaNumericCharacter(character: string): boolean {
|
||||
const characterCode: number = character.charCodeAt(0);
|
||||
return (
|
||||
(48 /* '0' */ <= characterCode && characterCode <= 57) /* '9' */ ||
|
||||
(65 /* 'A' */ <= characterCode && characterCode <= 90) /* 'Z' */ ||
|
||||
(97 /* 'a' */ <= characterCode && characterCode <= 122) /* 'z' */
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* A class that tokenizes URL strings.
|
||||
*/
|
||||
export class URLTokenizer {
|
||||
readonly _textLength: number;
|
||||
_currentState: URLTokenizerState;
|
||||
_currentIndex: number;
|
||||
_currentToken: URLToken | undefined;
|
||||
|
||||
public constructor(readonly _text: string, state?: URLTokenizerState) {
|
||||
this._textLength = _text ? _text.length : 0;
|
||||
this._currentState = state != undefined ? state : "SCHEME_OR_HOST";
|
||||
this._currentIndex = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current URLToken this URLTokenizer is pointing at, or undefined if the URLTokenizer
|
||||
* hasn't started or has finished tokenizing.
|
||||
*/
|
||||
public current(): URLToken | undefined {
|
||||
return this._currentToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* Advance to the next URLToken and return whether or not a URLToken was found.
|
||||
*/
|
||||
public next(): boolean {
|
||||
if (!hasCurrentCharacter(this)) {
|
||||
this._currentToken = undefined;
|
||||
} else {
|
||||
switch (this._currentState) {
|
||||
case "SCHEME":
|
||||
nextScheme(this);
|
||||
break;
|
||||
|
||||
case "SCHEME_OR_HOST":
|
||||
nextSchemeOrHost(this);
|
||||
break;
|
||||
|
||||
case "HOST":
|
||||
nextHost(this);
|
||||
break;
|
||||
|
||||
case "PORT":
|
||||
nextPort(this);
|
||||
break;
|
||||
|
||||
case "PATH":
|
||||
nextPath(this);
|
||||
break;
|
||||
|
||||
case "QUERY":
|
||||
nextQuery(this);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Error(`Unrecognized URLTokenizerState: ${this._currentState}`);
|
||||
}
|
||||
}
|
||||
return !!this._currentToken;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the remaining characters from this Tokenizer's character stream.
|
||||
*/
|
||||
function readRemaining(tokenizer: URLTokenizer): string {
|
||||
let result = "";
|
||||
if (tokenizer._currentIndex < tokenizer._textLength) {
|
||||
result = tokenizer._text.substring(tokenizer._currentIndex);
|
||||
tokenizer._currentIndex = tokenizer._textLength;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not this URLTokenizer has a current character.
|
||||
*/
|
||||
function hasCurrentCharacter(tokenizer: URLTokenizer): boolean {
|
||||
return tokenizer._currentIndex < tokenizer._textLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the character in the text string at the current index.
|
||||
*/
|
||||
function getCurrentCharacter(tokenizer: URLTokenizer): string {
|
||||
return tokenizer._text[tokenizer._currentIndex];
|
||||
}
|
||||
|
||||
/**
|
||||
* Advance to the character in text that is "step" characters ahead. If no step value is provided,
|
||||
* then step will default to 1.
|
||||
*/
|
||||
function nextCharacter(tokenizer: URLTokenizer, step?: number): void {
|
||||
if (hasCurrentCharacter(tokenizer)) {
|
||||
if (!step) {
|
||||
step = 1;
|
||||
}
|
||||
tokenizer._currentIndex += step;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Starting with the current character, peek "charactersToPeek" number of characters ahead in this
|
||||
* Tokenizer's stream of characters.
|
||||
*/
|
||||
function peekCharacters(tokenizer: URLTokenizer, charactersToPeek: number): string {
|
||||
let endIndex: number = tokenizer._currentIndex + charactersToPeek;
|
||||
if (tokenizer._textLength < endIndex) {
|
||||
endIndex = tokenizer._textLength;
|
||||
}
|
||||
return tokenizer._text.substring(tokenizer._currentIndex, endIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read characters from this Tokenizer until the end of the stream or until the provided condition
|
||||
* is false when provided the current character.
|
||||
*/
|
||||
function readWhile(tokenizer: URLTokenizer, condition: (character: string) => boolean): string {
|
||||
let result = "";
|
||||
|
||||
while (hasCurrentCharacter(tokenizer)) {
|
||||
const currentCharacter: string = getCurrentCharacter(tokenizer);
|
||||
if (!condition(currentCharacter)) {
|
||||
break;
|
||||
} else {
|
||||
result += currentCharacter;
|
||||
nextCharacter(tokenizer);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read characters from this Tokenizer until a non-alphanumeric character or the end of the
|
||||
* character stream is reached.
|
||||
*/
|
||||
function readWhileLetterOrDigit(tokenizer: URLTokenizer): string {
|
||||
return readWhile(tokenizer, (character: string) => isAlphaNumericCharacter(character));
|
||||
}
|
||||
|
||||
/**
|
||||
* Read characters from this Tokenizer until one of the provided terminating characters is read or
|
||||
* the end of the character stream is reached.
|
||||
*/
|
||||
function readUntilCharacter(tokenizer: URLTokenizer, ...terminatingCharacters: string[]): string {
|
||||
return readWhile(
|
||||
tokenizer,
|
||||
(character: string) => terminatingCharacters.indexOf(character) === -1
|
||||
);
|
||||
}
|
||||
|
||||
function nextScheme(tokenizer: URLTokenizer): void {
|
||||
const scheme: string = readWhileLetterOrDigit(tokenizer);
|
||||
tokenizer._currentToken = URLToken.scheme(scheme);
|
||||
if (!hasCurrentCharacter(tokenizer)) {
|
||||
tokenizer._currentState = "DONE";
|
||||
} else {
|
||||
tokenizer._currentState = "HOST";
|
||||
}
|
||||
}
|
||||
|
||||
function nextSchemeOrHost(tokenizer: URLTokenizer): void {
|
||||
const schemeOrHost: string = readUntilCharacter(tokenizer, ":", "/", "?");
|
||||
if (!hasCurrentCharacter(tokenizer)) {
|
||||
tokenizer._currentToken = URLToken.host(schemeOrHost);
|
||||
tokenizer._currentState = "DONE";
|
||||
} else if (getCurrentCharacter(tokenizer) === ":") {
|
||||
if (peekCharacters(tokenizer, 3) === "://") {
|
||||
tokenizer._currentToken = URLToken.scheme(schemeOrHost);
|
||||
tokenizer._currentState = "HOST";
|
||||
} else {
|
||||
tokenizer._currentToken = URLToken.host(schemeOrHost);
|
||||
tokenizer._currentState = "PORT";
|
||||
}
|
||||
} else {
|
||||
tokenizer._currentToken = URLToken.host(schemeOrHost);
|
||||
if (getCurrentCharacter(tokenizer) === "/") {
|
||||
tokenizer._currentState = "PATH";
|
||||
} else {
|
||||
tokenizer._currentState = "QUERY";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function nextHost(tokenizer: URLTokenizer): void {
|
||||
if (peekCharacters(tokenizer, 3) === "://") {
|
||||
nextCharacter(tokenizer, 3);
|
||||
}
|
||||
|
||||
const host: string = readUntilCharacter(tokenizer, ":", "/", "?");
|
||||
tokenizer._currentToken = URLToken.host(host);
|
||||
|
||||
if (!hasCurrentCharacter(tokenizer)) {
|
||||
tokenizer._currentState = "DONE";
|
||||
} else if (getCurrentCharacter(tokenizer) === ":") {
|
||||
tokenizer._currentState = "PORT";
|
||||
} else if (getCurrentCharacter(tokenizer) === "/") {
|
||||
tokenizer._currentState = "PATH";
|
||||
} else {
|
||||
tokenizer._currentState = "QUERY";
|
||||
}
|
||||
}
|
||||
|
||||
function nextPort(tokenizer: URLTokenizer): void {
|
||||
if (getCurrentCharacter(tokenizer) === ":") {
|
||||
nextCharacter(tokenizer);
|
||||
}
|
||||
|
||||
const port: string = readUntilCharacter(tokenizer, "/", "?");
|
||||
tokenizer._currentToken = URLToken.port(port);
|
||||
|
||||
if (!hasCurrentCharacter(tokenizer)) {
|
||||
tokenizer._currentState = "DONE";
|
||||
} else if (getCurrentCharacter(tokenizer) === "/") {
|
||||
tokenizer._currentState = "PATH";
|
||||
} else {
|
||||
tokenizer._currentState = "QUERY";
|
||||
}
|
||||
}
|
||||
|
||||
function nextPath(tokenizer: URLTokenizer): void {
|
||||
const path: string = readUntilCharacter(tokenizer, "?");
|
||||
tokenizer._currentToken = URLToken.path(path);
|
||||
|
||||
if (!hasCurrentCharacter(tokenizer)) {
|
||||
tokenizer._currentState = "DONE";
|
||||
} else {
|
||||
tokenizer._currentState = "QUERY";
|
||||
}
|
||||
}
|
||||
|
||||
function nextQuery(tokenizer: URLTokenizer): void {
|
||||
if (getCurrentCharacter(tokenizer) === "?") {
|
||||
nextCharacter(tokenizer);
|
||||
}
|
||||
|
||||
const query: string = readRemaining(tokenizer);
|
||||
tokenizer._currentToken = URLToken.query(query);
|
||||
tokenizer._currentState = "DONE";
|
||||
}
|
35
node_modules/@azure/ms-rest-js/lib/util/base64.browser.ts
generated
vendored
Normal file
35
node_modules/@azure/ms-rest-js/lib/util/base64.browser.ts
generated
vendored
Normal file
|
@ -0,0 +1,35 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
/**
|
||||
* Encodes a string in base64 format.
|
||||
* @param value the string to encode
|
||||
*/
|
||||
export function encodeString(value: string): string {
|
||||
return btoa(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes a byte array in base64 format.
|
||||
* @param value the Uint8Aray to encode
|
||||
*/
|
||||
export function encodeByteArray(value: Uint8Array): string {
|
||||
let str = "";
|
||||
for (let i = 0; i < value.length; i++) {
|
||||
str += String.fromCharCode(value[i]);
|
||||
}
|
||||
return btoa(str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes a base64 string into a byte array.
|
||||
* @param value the base64 string to decode
|
||||
*/
|
||||
export function decodeString(value: string): Uint8Array {
|
||||
const byteString = atob(value);
|
||||
const arr = new Uint8Array(byteString.length);
|
||||
for (let i = 0; i < byteString.length; i++) {
|
||||
arr[i] = byteString.charCodeAt(i);
|
||||
}
|
||||
return arr;
|
||||
}
|
29
node_modules/@azure/ms-rest-js/lib/util/base64.ts
generated
vendored
Normal file
29
node_modules/@azure/ms-rest-js/lib/util/base64.ts
generated
vendored
Normal file
|
@ -0,0 +1,29 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
/**
|
||||
* Encodes a string in base64 format.
|
||||
* @param value the string to encode
|
||||
*/
|
||||
export function encodeString(value: string): string {
|
||||
return Buffer.from(value).toString("base64");
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes a byte array in base64 format.
|
||||
* @param value the Uint8Aray to encode
|
||||
*/
|
||||
export function encodeByteArray(value: Uint8Array): string {
|
||||
// Buffer.from accepts <ArrayBuffer> | <SharedArrayBuffer>-- the TypeScript definition is off here
|
||||
// https://nodejs.org/api/buffer.html#buffer_class_method_buffer_from_arraybuffer_byteoffset_length
|
||||
const bufferValue = value instanceof Buffer ? value : Buffer.from(value.buffer as ArrayBuffer);
|
||||
return bufferValue.toString("base64");
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes a base64 string into a byte array.
|
||||
* @param value the base64 string to decode
|
||||
*/
|
||||
export function decodeString(value: string): Uint8Array {
|
||||
return Buffer.from(value, "base64");
|
||||
}
|
108
node_modules/@azure/ms-rest-js/lib/util/constants.ts
generated
vendored
Normal file
108
node_modules/@azure/ms-rest-js/lib/util/constants.ts
generated
vendored
Normal file
|
@ -0,0 +1,108 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
export const Constants = {
|
||||
/**
|
||||
* The ms-rest version
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
msRestVersion: "2.6.1",
|
||||
|
||||
/**
|
||||
* Specifies HTTP.
|
||||
*
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
HTTP: "http:",
|
||||
|
||||
/**
|
||||
* Specifies HTTPS.
|
||||
*
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
HTTPS: "https:",
|
||||
|
||||
/**
|
||||
* Specifies HTTP Proxy.
|
||||
*
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
HTTP_PROXY: "HTTP_PROXY",
|
||||
|
||||
/**
|
||||
* Specifies HTTPS Proxy.
|
||||
*
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
HTTPS_PROXY: "HTTPS_PROXY",
|
||||
|
||||
/**
|
||||
* Specifies NO Proxy.
|
||||
*/
|
||||
NO_PROXY: "NO_PROXY",
|
||||
|
||||
/**
|
||||
* Specifies ALL Proxy.
|
||||
*/
|
||||
ALL_PROXY: "ALL_PROXY",
|
||||
|
||||
HttpConstants: {
|
||||
/**
|
||||
* Http Verbs
|
||||
*
|
||||
* @const
|
||||
* @enum {string}
|
||||
*/
|
||||
HttpVerbs: {
|
||||
PUT: "PUT",
|
||||
GET: "GET",
|
||||
DELETE: "DELETE",
|
||||
POST: "POST",
|
||||
MERGE: "MERGE",
|
||||
HEAD: "HEAD",
|
||||
PATCH: "PATCH",
|
||||
},
|
||||
|
||||
StatusCodes: {
|
||||
TooManyRequests: 429,
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* Defines constants for use with HTTP headers.
|
||||
*/
|
||||
HeaderConstants: {
|
||||
/**
|
||||
* The Authorization header.
|
||||
*
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
AUTHORIZATION: "authorization",
|
||||
|
||||
AUTHORIZATION_SCHEME: "Bearer",
|
||||
|
||||
/**
|
||||
* The Retry-After response-header field can be used with a 503 (Service
|
||||
* Unavailable) or 349 (Too Many Requests) responses to indicate how long
|
||||
* the service is expected to be unavailable to the requesting client.
|
||||
*
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
RETRY_AFTER: "Retry-After",
|
||||
|
||||
/**
|
||||
* The UserAgent header.
|
||||
*
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
USER_AGENT: "User-Agent",
|
||||
},
|
||||
};
|
288
node_modules/@azure/ms-rest-js/lib/util/utils.ts
generated
vendored
Normal file
288
node_modules/@azure/ms-rest-js/lib/util/utils.ts
generated
vendored
Normal file
|
@ -0,0 +1,288 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import { HttpOperationResponse } from "../httpOperationResponse";
|
||||
import { RestError } from "../restError";
|
||||
import { WebResourceLike } from "../webResource";
|
||||
import { Constants } from "./constants";
|
||||
|
||||
/**
|
||||
* A constant that indicates whether the environment is node.js or browser based.
|
||||
*/
|
||||
export const isNode =
|
||||
typeof process !== "undefined" &&
|
||||
!!process.version &&
|
||||
!!process.versions &&
|
||||
!!process.versions.node;
|
||||
|
||||
/**
|
||||
* Checks if a parsed URL is HTTPS
|
||||
*
|
||||
* @param {object} urlToCheck The url to check
|
||||
* @return {boolean} True if the URL is HTTPS; false otherwise.
|
||||
*/
|
||||
export function urlIsHTTPS(urlToCheck: { protocol: string }): boolean {
|
||||
return urlToCheck.protocol.toLowerCase() === Constants.HTTPS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes an URI.
|
||||
*
|
||||
* @param {string} uri The URI to be encoded.
|
||||
* @return {string} The encoded URI.
|
||||
*/
|
||||
export function encodeUri(uri: string): string {
|
||||
return encodeURIComponent(uri)
|
||||
.replace(/!/g, "%21")
|
||||
.replace(/"/g, "%27")
|
||||
.replace(/\(/g, "%28")
|
||||
.replace(/\)/g, "%29")
|
||||
.replace(/\*/g, "%2A");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a stripped version of the Http Response which only contains body,
|
||||
* headers and the status.
|
||||
*
|
||||
* @param {HttpOperationResponse} response The Http Response
|
||||
*
|
||||
* @return {object} The stripped version of Http Response.
|
||||
*/
|
||||
export function stripResponse(response: HttpOperationResponse): any {
|
||||
const strippedResponse: any = {};
|
||||
strippedResponse.body = response.bodyAsText;
|
||||
strippedResponse.headers = response.headers;
|
||||
strippedResponse.status = response.status;
|
||||
return strippedResponse;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a stripped version of the Http Request that does not contain the
|
||||
* Authorization header.
|
||||
*
|
||||
* @param {WebResource} request The Http Request object
|
||||
*
|
||||
* @return {WebResource} The stripped version of Http Request.
|
||||
*/
|
||||
export function stripRequest(request: WebResourceLike): WebResourceLike {
|
||||
const strippedRequest = request.clone();
|
||||
if (strippedRequest.headers) {
|
||||
strippedRequest.headers.remove("authorization");
|
||||
}
|
||||
return strippedRequest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the given uuid as a string
|
||||
*
|
||||
* @param {string} uuid The uuid as a string that needs to be validated
|
||||
*
|
||||
* @return {boolean} True if the uuid is valid; false otherwise.
|
||||
*/
|
||||
export function isValidUuid(uuid: string): boolean {
|
||||
const validUuidRegex = new RegExp(
|
||||
"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$",
|
||||
"ig"
|
||||
);
|
||||
return validUuidRegex.test(uuid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides an array of values of an object. For example
|
||||
* for a given object { "a": "foo", "b": "bar" }, the method returns ["foo", "bar"].
|
||||
*
|
||||
* @param {object} obj An object whose properties need to be enumerated so that it"s values can be provided as an array
|
||||
*
|
||||
* @return {any[]} An array of values of the given object.
|
||||
*/
|
||||
export function objectValues(obj: { [key: string]: any }): any[] {
|
||||
const result: any[] = [];
|
||||
if (obj && obj instanceof Object) {
|
||||
for (const key in obj) {
|
||||
if (obj.hasOwnProperty(key)) {
|
||||
result.push((<any>obj)[key]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new Error(
|
||||
`The provided object ${JSON.stringify(
|
||||
obj,
|
||||
undefined,
|
||||
2
|
||||
)} is not a valid object that can be ` + `enumerated to provide its values as an array.`
|
||||
);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generated UUID
|
||||
*
|
||||
* @return {string} RFC4122 v4 UUID.
|
||||
*/
|
||||
export function generateUuid(): string {
|
||||
return uuidv4();
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes an array of promises sequentially. Inspiration of this method is here:
|
||||
* https://pouchdb.com/2015/05/18/we-have-a-problem-with-promises.html. An awesome blog on promises!
|
||||
*
|
||||
* @param {Array} promiseFactories An array of promise factories(A function that return a promise)
|
||||
*
|
||||
* @param {any} [kickstart] Input to the first promise that is used to kickstart the promise chain.
|
||||
* If not provided then the promise chain starts with undefined.
|
||||
*
|
||||
* @return A chain of resolved or rejected promises
|
||||
*/
|
||||
export function executePromisesSequentially(promiseFactories: Array<any>, kickstart: any) {
|
||||
let result = Promise.resolve(kickstart);
|
||||
promiseFactories.forEach((promiseFactory) => {
|
||||
result = result.then(promiseFactory);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges source object into the target object
|
||||
* @param {object} source The object that needs to be merged
|
||||
*
|
||||
* @param {object} target The object to be merged into
|
||||
*
|
||||
* @returns {object} Returns the merged target object.
|
||||
*/
|
||||
export function mergeObjects(source: { [key: string]: any }, target: { [key: string]: any }) {
|
||||
Object.keys(source).forEach((key) => {
|
||||
target[key] = source[key];
|
||||
});
|
||||
return target;
|
||||
}
|
||||
|
||||
/**
|
||||
* A wrapper for setTimeout that resolves a promise after t milliseconds.
|
||||
* @param {number} t The number of milliseconds to be delayed.
|
||||
* @param {T} value The value to be resolved with after a timeout of t milliseconds.
|
||||
* @returns {Promise<T>} Resolved promise
|
||||
*/
|
||||
export function delay<T>(t: number, value?: T): Promise<T> {
|
||||
return new Promise((resolve) => setTimeout(() => resolve(value), t));
|
||||
}
|
||||
|
||||
/**
|
||||
* Service callback that is returned for REST requests initiated by the service client.
|
||||
*/
|
||||
export interface ServiceCallback<TResult> {
|
||||
/**
|
||||
* A method that will be invoked as a callback to a service function.
|
||||
* @param {Error | RestError | null} err The error occurred if any, while executing the request; otherwise null.
|
||||
* @param {TResult} [result] The deserialized response body if an error did not occur.
|
||||
* @param {WebResourceLike} [request] The raw/actual request sent to the server if an error did not occur.
|
||||
* @param {HttpOperationResponse} [response] The raw/actual response from the server if an error did not occur.
|
||||
*/
|
||||
(
|
||||
err: Error | RestError | null,
|
||||
result?: TResult,
|
||||
request?: WebResourceLike,
|
||||
response?: HttpOperationResponse
|
||||
): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a Promise to a callback.
|
||||
* @param {Promise<any>} promise The Promise to be converted to a callback
|
||||
* @returns {Function} A function that takes the callback (cb: Function): void
|
||||
* @deprecated generated code should instead depend on responseToBody
|
||||
*/
|
||||
export function promiseToCallback(promise: Promise<any>): Function {
|
||||
if (typeof promise.then !== "function") {
|
||||
throw new Error("The provided input is not a Promise.");
|
||||
}
|
||||
return (cb: Function): void => {
|
||||
promise.then(
|
||||
(data: any) => {
|
||||
cb(undefined, data);
|
||||
},
|
||||
(err: Error) => {
|
||||
cb(err);
|
||||
}
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a Promise to a service callback.
|
||||
* @param {Promise<HttpOperationResponse>} promise - The Promise of HttpOperationResponse to be converted to a service callback
|
||||
* @returns {Function} A function that takes the service callback (cb: ServiceCallback<T>): void
|
||||
*/
|
||||
export function promiseToServiceCallback<T>(promise: Promise<HttpOperationResponse>): Function {
|
||||
if (typeof promise.then !== "function") {
|
||||
throw new Error("The provided input is not a Promise.");
|
||||
}
|
||||
return (cb: ServiceCallback<T>): void => {
|
||||
promise.then(
|
||||
(data: HttpOperationResponse) => {
|
||||
process.nextTick(cb, undefined, data.parsedBody as T, data.request, data);
|
||||
},
|
||||
(err: Error) => {
|
||||
process.nextTick(cb, err);
|
||||
}
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
export function prepareXMLRootList(obj: any, elementName: string) {
|
||||
if (!Array.isArray(obj)) {
|
||||
obj = [obj];
|
||||
}
|
||||
return { [elementName]: obj };
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the properties on the prototype of sourceCtors to the prototype of targetCtor
|
||||
* @param {object} targetCtor The target object on which the properties need to be applied.
|
||||
* @param {Array<object>} sourceCtors An array of source objects from which the properties need to be taken.
|
||||
*/
|
||||
export function applyMixins(targetCtor: any, sourceCtors: any[]): void {
|
||||
sourceCtors.forEach((sourceCtors) => {
|
||||
Object.getOwnPropertyNames(sourceCtors.prototype).forEach((name) => {
|
||||
targetCtor.prototype[name] = sourceCtors.prototype[name];
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const validateISODuration = /^(-|\+)?P(?:([-+]?[0-9,.]*)Y)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)W)?(?:([-+]?[0-9,.]*)D)?(?:T(?:([-+]?[0-9,.]*)H)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)S)?)?$/;
|
||||
|
||||
/**
|
||||
* Indicates whether the given string is in ISO 8601 format.
|
||||
* @param {string} value The value to be validated for ISO 8601 duration format.
|
||||
* @return {boolean} `true` if valid, `false` otherwise.
|
||||
*/
|
||||
export function isDuration(value: string): boolean {
|
||||
return validateISODuration.test(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace all of the instances of searchValue in value with the provided replaceValue.
|
||||
* @param {string | undefined} value The value to search and replace in.
|
||||
* @param {string} searchValue The value to search for in the value argument.
|
||||
* @param {string} replaceValue The value to replace searchValue with in the value argument.
|
||||
* @returns {string | undefined} The value where each instance of searchValue was replaced with replacedValue.
|
||||
*/
|
||||
export function replaceAll(
|
||||
value: string | undefined,
|
||||
searchValue: string,
|
||||
replaceValue: string
|
||||
): string | undefined {
|
||||
return !value || !searchValue ? value : value.split(searchValue).join(replaceValue || "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the given enity is a basic/primitive type
|
||||
* (string, number, boolean, null, undefined).
|
||||
* @param value Any entity
|
||||
* @return boolean - true is it is primitive type, false otherwise.
|
||||
*/
|
||||
export function isPrimitiveType(value: any): boolean {
|
||||
return (typeof value !== "object" && typeof value !== "function") || value === null;
|
||||
}
|
149
node_modules/@azure/ms-rest-js/lib/util/xml.browser.ts
generated
vendored
Normal file
149
node_modules/@azure/ms-rest-js/lib/util/xml.browser.ts
generated
vendored
Normal file
|
@ -0,0 +1,149 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
const parser = new DOMParser();
|
||||
export function parseXML(str: string): Promise<any> {
|
||||
try {
|
||||
const dom = parser.parseFromString(str, "application/xml");
|
||||
throwIfError(dom);
|
||||
|
||||
const obj = domToObject(dom.childNodes[0]);
|
||||
return Promise.resolve(obj);
|
||||
} catch (err) {
|
||||
return Promise.reject(err);
|
||||
}
|
||||
}
|
||||
|
||||
let errorNS = "";
|
||||
try {
|
||||
errorNS = parser.parseFromString("INVALID", "text/xml").getElementsByTagName("parsererror")[0]
|
||||
.namespaceURI!;
|
||||
} catch (ignored) {
|
||||
// Most browsers will return a document containing <parsererror>, but IE will throw.
|
||||
}
|
||||
|
||||
function throwIfError(dom: Document) {
|
||||
if (errorNS) {
|
||||
const parserErrors = dom.getElementsByTagNameNS(errorNS, "parsererror");
|
||||
if (parserErrors.length) {
|
||||
throw new Error(parserErrors.item(0)!.innerHTML);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function isElement(node: Node): node is Element {
|
||||
return !!(node as Element).attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Element-typed version of the provided Node if the provided node is an element with
|
||||
* attributes. If it isn't, then undefined is returned.
|
||||
*/
|
||||
function asElementWithAttributes(node: Node): Element | undefined {
|
||||
return isElement(node) && node.hasAttributes() ? node : undefined;
|
||||
}
|
||||
|
||||
function domToObject(node: Node): any {
|
||||
let result: any = {};
|
||||
|
||||
const childNodeCount: number = node.childNodes.length;
|
||||
|
||||
const firstChildNode: Node = node.childNodes[0];
|
||||
const onlyChildTextValue: string | undefined =
|
||||
(firstChildNode &&
|
||||
childNodeCount === 1 &&
|
||||
firstChildNode.nodeType === Node.TEXT_NODE &&
|
||||
firstChildNode.nodeValue) ||
|
||||
undefined;
|
||||
|
||||
const elementWithAttributes: Element | undefined = asElementWithAttributes(node);
|
||||
if (elementWithAttributes) {
|
||||
result["$"] = {};
|
||||
|
||||
for (let i = 0; i < elementWithAttributes.attributes.length; i++) {
|
||||
const attr = elementWithAttributes.attributes[i];
|
||||
result["$"][attr.nodeName] = attr.nodeValue;
|
||||
}
|
||||
|
||||
if (onlyChildTextValue) {
|
||||
result["_"] = onlyChildTextValue;
|
||||
}
|
||||
} else if (childNodeCount === 0) {
|
||||
result = "";
|
||||
} else if (onlyChildTextValue) {
|
||||
result = onlyChildTextValue;
|
||||
}
|
||||
|
||||
if (!onlyChildTextValue) {
|
||||
for (let i = 0; i < childNodeCount; i++) {
|
||||
const child = node.childNodes[i];
|
||||
// Ignore leading/trailing whitespace nodes
|
||||
if (child.nodeType !== Node.TEXT_NODE) {
|
||||
const childObject: any = domToObject(child);
|
||||
if (!result[child.nodeName]) {
|
||||
result[child.nodeName] = childObject;
|
||||
} else if (Array.isArray(result[child.nodeName])) {
|
||||
result[child.nodeName].push(childObject);
|
||||
} else {
|
||||
result[child.nodeName] = [result[child.nodeName], childObject];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// tslint:disable-next-line:no-null-keyword
|
||||
const doc = document.implementation.createDocument(null, null, null);
|
||||
const serializer = new XMLSerializer();
|
||||
|
||||
export function stringifyXML(obj: any, opts?: { rootName?: string }) {
|
||||
const rootName = (opts && opts.rootName) || "root";
|
||||
const dom = buildNode(obj, rootName)[0];
|
||||
return (
|
||||
'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' + serializer.serializeToString(dom)
|
||||
);
|
||||
}
|
||||
|
||||
function buildAttributes(attrs: { [key: string]: { toString(): string } }): Attr[] {
|
||||
const result = [];
|
||||
for (const key of Object.keys(attrs)) {
|
||||
const attr = doc.createAttribute(key);
|
||||
attr.value = attrs[key].toString();
|
||||
result.push(attr);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function buildNode(obj: any, elementName: string): Node[] {
|
||||
if (typeof obj === "string" || typeof obj === "number" || typeof obj === "boolean") {
|
||||
const elem = doc.createElement(elementName);
|
||||
elem.textContent = obj.toString();
|
||||
return [elem];
|
||||
} else if (Array.isArray(obj)) {
|
||||
const result = [];
|
||||
for (const arrayElem of obj) {
|
||||
for (const child of buildNode(arrayElem, elementName)) {
|
||||
result.push(child);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
} else if (typeof obj === "object") {
|
||||
const elem = doc.createElement(elementName);
|
||||
for (const key of Object.keys(obj)) {
|
||||
if (key === "$") {
|
||||
for (const attr of buildAttributes(obj[key])) {
|
||||
elem.attributes.setNamedItem(attr);
|
||||
}
|
||||
} else {
|
||||
for (const child of buildNode(obj[key], key)) {
|
||||
elem.appendChild(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
return [elem];
|
||||
} else {
|
||||
throw new Error(`Illegal value passed to buildObject: ${obj}`);
|
||||
}
|
||||
}
|
35
node_modules/@azure/ms-rest-js/lib/util/xml.ts
generated
vendored
Normal file
35
node_modules/@azure/ms-rest-js/lib/util/xml.ts
generated
vendored
Normal file
|
@ -0,0 +1,35 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
import * as xml2js from "xml2js";
|
||||
|
||||
export function stringifyXML(obj: any, opts?: { rootName?: string }) {
|
||||
const builder = new xml2js.Builder({
|
||||
rootName: (opts || {}).rootName,
|
||||
renderOpts: {
|
||||
pretty: false,
|
||||
},
|
||||
});
|
||||
return builder.buildObject(obj);
|
||||
}
|
||||
|
||||
export function parseXML(str: string): Promise<any> {
|
||||
const xmlParser = new xml2js.Parser({
|
||||
explicitArray: false,
|
||||
explicitCharkey: false,
|
||||
explicitRoot: false,
|
||||
});
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!str) {
|
||||
reject(new Error("Document is empty"));
|
||||
} else {
|
||||
xmlParser.parseString(str, (err?: Error, res?: any) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
resolve(res);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
668
node_modules/@azure/ms-rest-js/lib/webResource.ts
generated
vendored
Normal file
668
node_modules/@azure/ms-rest-js/lib/webResource.ts
generated
vendored
Normal file
|
@ -0,0 +1,668 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
import { HttpHeaders, HttpHeadersLike, isHttpHeadersLike } from "./httpHeaders";
|
||||
import { OperationSpec } from "./operationSpec";
|
||||
import { Mapper, Serializer } from "./serializer";
|
||||
import { generateUuid } from "./util/utils";
|
||||
import { HttpOperationResponse } from "./httpOperationResponse";
|
||||
import { OperationResponse } from "./operationResponse";
|
||||
import { AgentSettings, ProxySettings } from "./serviceClient";
|
||||
|
||||
export type HttpMethods =
|
||||
| "GET"
|
||||
| "PUT"
|
||||
| "POST"
|
||||
| "DELETE"
|
||||
| "PATCH"
|
||||
| "HEAD"
|
||||
| "OPTIONS"
|
||||
| "TRACE";
|
||||
export type HttpRequestBody =
|
||||
| Blob
|
||||
| string
|
||||
| ArrayBuffer
|
||||
| ArrayBufferView
|
||||
| (() => NodeJS.ReadableStream);
|
||||
|
||||
/**
|
||||
* Fired in response to upload or download progress.
|
||||
*/
|
||||
export type TransferProgressEvent = {
|
||||
/**
|
||||
* The number of bytes loaded so far.
|
||||
*/
|
||||
loadedBytes: number;
|
||||
};
|
||||
|
||||
/**
|
||||
* Allows the request to be aborted upon firing of the "abort" event.
|
||||
* Compatible with the browser built-in AbortSignal and common polyfills.
|
||||
*/
|
||||
export interface AbortSignalLike {
|
||||
readonly aborted: boolean;
|
||||
dispatchEvent: (event: Event) => boolean;
|
||||
onabort: ((this: AbortSignalLike, ev: Event) => any) | null;
|
||||
addEventListener: (
|
||||
type: "abort",
|
||||
listener: (this: AbortSignalLike, ev: Event) => any,
|
||||
options?: any
|
||||
) => void;
|
||||
removeEventListener: (
|
||||
type: "abort",
|
||||
listener: (this: AbortSignalLike, ev: Event) => any,
|
||||
options?: any
|
||||
) => void;
|
||||
}
|
||||
|
||||
/**
|
||||
* An abstraction over a REST call.
|
||||
*/
|
||||
export interface WebResourceLike {
|
||||
/**
|
||||
* The URL being accessed by the request.
|
||||
*/
|
||||
url: string;
|
||||
/**
|
||||
* The HTTP method to use when making the request.
|
||||
*/
|
||||
method: HttpMethods;
|
||||
/**
|
||||
* The HTTP body contents of the request.
|
||||
*/
|
||||
body?: any;
|
||||
/**
|
||||
* The HTTP headers to use when making the request.
|
||||
*/
|
||||
headers: HttpHeadersLike;
|
||||
/**
|
||||
* Whether or not the body of the HttpOperationResponse should be treated as a stream.
|
||||
*/
|
||||
streamResponseBody?: boolean;
|
||||
/**
|
||||
* Whether or not the HttpOperationResponse should be deserialized. If this is undefined, then the
|
||||
* HttpOperationResponse should be deserialized.
|
||||
*/
|
||||
shouldDeserialize?: boolean | ((response: HttpOperationResponse) => boolean);
|
||||
/**
|
||||
* A function that returns the proper OperationResponse for the given OperationSpec and
|
||||
* HttpOperationResponse combination. If this is undefined, then a simple status code lookup will
|
||||
* be used.
|
||||
*/
|
||||
operationResponseGetter?: (
|
||||
operationSpec: OperationSpec,
|
||||
response: HttpOperationResponse
|
||||
) => undefined | OperationResponse;
|
||||
formData?: any;
|
||||
/**
|
||||
* A query string represented as an object.
|
||||
*/
|
||||
query?: { [key: string]: any };
|
||||
/**
|
||||
* Used to parse the response.
|
||||
*/
|
||||
operationSpec?: OperationSpec;
|
||||
/**
|
||||
* If credentials (cookies) should be sent along during an XHR.
|
||||
*/
|
||||
withCredentials: boolean;
|
||||
/**
|
||||
* The number of milliseconds a request can take before automatically being terminated.
|
||||
* If the request is terminated, an `AbortError` is thrown.
|
||||
*/
|
||||
timeout: number;
|
||||
/**
|
||||
* Proxy configuration.
|
||||
*/
|
||||
proxySettings?: ProxySettings;
|
||||
/**
|
||||
* HTTP(S) agent configuration.
|
||||
*/
|
||||
agentSettings?: AgentSettings;
|
||||
/**
|
||||
* If the connection should be reused.
|
||||
*/
|
||||
keepAlive?: boolean;
|
||||
/**
|
||||
* Limit the number of redirects followed for this request. If set to 0, redirects will not be followed.
|
||||
* If left undefined the default redirect behaviour of the underlying node_fetch will apply.
|
||||
*/
|
||||
redirectLimit?: number;
|
||||
|
||||
/**
|
||||
* Used to abort the request later.
|
||||
*/
|
||||
abortSignal?: AbortSignalLike;
|
||||
|
||||
/**
|
||||
* Callback which fires upon upload progress.
|
||||
*/
|
||||
onUploadProgress?: (progress: TransferProgressEvent) => void;
|
||||
|
||||
/** Callback which fires upon download progress. */
|
||||
onDownloadProgress?: (progress: TransferProgressEvent) => void;
|
||||
|
||||
/**
|
||||
* Validates that the required properties such as method, url, headers["Content-Type"],
|
||||
* headers["accept-language"] are defined. It will throw an error if one of the above
|
||||
* mentioned properties are not defined.
|
||||
*/
|
||||
validateRequestProperties(): void;
|
||||
|
||||
/**
|
||||
* Sets options on the request.
|
||||
*/
|
||||
prepare(options: RequestPrepareOptions): WebResourceLike;
|
||||
/**
|
||||
* Clone this request object.
|
||||
*/
|
||||
clone(): WebResourceLike;
|
||||
}
|
||||
|
||||
export function isWebResourceLike(object: any): object is WebResourceLike {
|
||||
if (typeof object !== "object") {
|
||||
return false;
|
||||
}
|
||||
if (
|
||||
typeof object.url === "string" &&
|
||||
typeof object.method === "string" &&
|
||||
typeof object.headers === "object" &&
|
||||
isHttpHeadersLike(object.headers) &&
|
||||
typeof object.validateRequestProperties === "function" &&
|
||||
typeof object.prepare === "function" &&
|
||||
typeof object.clone === "function"
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new WebResource object.
|
||||
*
|
||||
* This class provides an abstraction over a REST call by being library / implementation agnostic and wrapping the necessary
|
||||
* properties to initiate a request.
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
export class WebResource {
|
||||
url: string;
|
||||
method: HttpMethods;
|
||||
body?: any;
|
||||
headers: HttpHeadersLike;
|
||||
/**
|
||||
* Whether or not the body of the HttpOperationResponse should be treated as a stream.
|
||||
*/
|
||||
streamResponseBody?: boolean;
|
||||
/**
|
||||
* Whether or not the HttpOperationResponse should be deserialized. If this is undefined, then the
|
||||
* HttpOperationResponse should be deserialized.
|
||||
*/
|
||||
shouldDeserialize?: boolean | ((response: HttpOperationResponse) => boolean);
|
||||
/**
|
||||
* A function that returns the proper OperationResponse for the given OperationSpec and
|
||||
* HttpOperationResponse combination. If this is undefined, then a simple status code lookup will
|
||||
* be used.
|
||||
*/
|
||||
operationResponseGetter?: (
|
||||
operationSpec: OperationSpec,
|
||||
response: HttpOperationResponse
|
||||
) => undefined | OperationResponse;
|
||||
formData?: any;
|
||||
query?: { [key: string]: any };
|
||||
operationSpec?: OperationSpec;
|
||||
withCredentials: boolean;
|
||||
timeout: number;
|
||||
proxySettings?: ProxySettings;
|
||||
keepAlive?: boolean;
|
||||
agentSettings?: AgentSettings;
|
||||
redirectLimit?: number;
|
||||
|
||||
abortSignal?: AbortSignalLike;
|
||||
|
||||
/** Callback which fires upon upload progress. */
|
||||
onUploadProgress?: (progress: TransferProgressEvent) => void;
|
||||
|
||||
/** Callback which fires upon download progress. */
|
||||
onDownloadProgress?: (progress: TransferProgressEvent) => void;
|
||||
|
||||
constructor(
|
||||
url?: string,
|
||||
method?: HttpMethods,
|
||||
body?: any,
|
||||
query?: { [key: string]: any },
|
||||
headers?: { [key: string]: any } | HttpHeadersLike,
|
||||
streamResponseBody?: boolean,
|
||||
withCredentials?: boolean,
|
||||
abortSignal?: AbortSignalLike,
|
||||
timeout?: number,
|
||||
onUploadProgress?: (progress: TransferProgressEvent) => void,
|
||||
onDownloadProgress?: (progress: TransferProgressEvent) => void,
|
||||
proxySettings?: ProxySettings,
|
||||
keepAlive?: boolean,
|
||||
agentSettings?: AgentSettings,
|
||||
redirectLimit?: number
|
||||
) {
|
||||
this.streamResponseBody = streamResponseBody;
|
||||
this.url = url || "";
|
||||
this.method = method || "GET";
|
||||
this.headers = isHttpHeadersLike(headers) ? headers : new HttpHeaders(headers);
|
||||
this.body = body;
|
||||
this.query = query;
|
||||
this.formData = undefined;
|
||||
this.withCredentials = withCredentials || false;
|
||||
this.abortSignal = abortSignal;
|
||||
this.timeout = timeout || 0;
|
||||
this.onUploadProgress = onUploadProgress;
|
||||
this.onDownloadProgress = onDownloadProgress;
|
||||
this.proxySettings = proxySettings;
|
||||
this.keepAlive = keepAlive;
|
||||
this.agentSettings = agentSettings;
|
||||
this.redirectLimit = redirectLimit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates that the required properties such as method, url, headers["Content-Type"],
|
||||
* headers["accept-language"] are defined. It will throw an error if one of the above
|
||||
* mentioned properties are not defined.
|
||||
*/
|
||||
validateRequestProperties(): void {
|
||||
if (!this.method) {
|
||||
throw new Error("WebResource.method is required.");
|
||||
}
|
||||
if (!this.url) {
|
||||
throw new Error("WebResource.url is required.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the request.
|
||||
* @param {RequestPrepareOptions} options Options to provide for preparing the request.
|
||||
* @returns {WebResource} Returns the prepared WebResource (HTTP Request) object that needs to be given to the request pipeline.
|
||||
*/
|
||||
prepare(options: RequestPrepareOptions): WebResource {
|
||||
if (!options) {
|
||||
throw new Error("options object is required");
|
||||
}
|
||||
|
||||
if (options.method == undefined || typeof options.method.valueOf() !== "string") {
|
||||
throw new Error("options.method must be a string.");
|
||||
}
|
||||
|
||||
if (options.url && options.pathTemplate) {
|
||||
throw new Error(
|
||||
"options.url and options.pathTemplate are mutually exclusive. Please provide exactly one of them."
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
(options.pathTemplate == undefined || typeof options.pathTemplate.valueOf() !== "string") &&
|
||||
(options.url == undefined || typeof options.url.valueOf() !== "string")
|
||||
) {
|
||||
throw new Error("Please provide exactly one of options.pathTemplate or options.url.");
|
||||
}
|
||||
|
||||
// set the url if it is provided.
|
||||
if (options.url) {
|
||||
if (typeof options.url !== "string") {
|
||||
throw new Error('options.url must be of type "string".');
|
||||
}
|
||||
this.url = options.url;
|
||||
}
|
||||
|
||||
// set the method
|
||||
if (options.method) {
|
||||
const validMethods = ["GET", "PUT", "HEAD", "DELETE", "OPTIONS", "POST", "PATCH", "TRACE"];
|
||||
if (validMethods.indexOf(options.method.toUpperCase()) === -1) {
|
||||
throw new Error(
|
||||
'The provided method "' +
|
||||
options.method +
|
||||
'" is invalid. Supported HTTP methods are: ' +
|
||||
JSON.stringify(validMethods)
|
||||
);
|
||||
}
|
||||
}
|
||||
this.method = options.method.toUpperCase() as HttpMethods;
|
||||
|
||||
// construct the url if path template is provided
|
||||
if (options.pathTemplate) {
|
||||
const { pathTemplate, pathParameters } = options;
|
||||
if (typeof pathTemplate !== "string") {
|
||||
throw new Error('options.pathTemplate must be of type "string".');
|
||||
}
|
||||
if (!options.baseUrl) {
|
||||
options.baseUrl = "https://management.azure.com";
|
||||
}
|
||||
const baseUrl = options.baseUrl;
|
||||
let url =
|
||||
baseUrl +
|
||||
(baseUrl.endsWith("/") ? "" : "/") +
|
||||
(pathTemplate.startsWith("/") ? pathTemplate.slice(1) : pathTemplate);
|
||||
const segments = url.match(/({\w*\s*\w*})/gi);
|
||||
if (segments && segments.length) {
|
||||
if (!pathParameters) {
|
||||
throw new Error(
|
||||
`pathTemplate: ${pathTemplate} has been provided. Hence, options.pathParameters must also be provided.`
|
||||
);
|
||||
}
|
||||
segments.forEach(function (item) {
|
||||
const pathParamName = item.slice(1, -1);
|
||||
const pathParam = (pathParameters as { [key: string]: any })[pathParamName];
|
||||
if (
|
||||
pathParam === null ||
|
||||
pathParam === undefined ||
|
||||
!(typeof pathParam === "string" || typeof pathParam === "object")
|
||||
) {
|
||||
throw new Error(
|
||||
`pathTemplate: ${pathTemplate} contains the path parameter ${pathParamName}` +
|
||||
` however, it is not present in ${pathParameters} - ${JSON.stringify(
|
||||
pathParameters,
|
||||
undefined,
|
||||
2
|
||||
)}.` +
|
||||
`The value of the path parameter can either be a "string" of the form { ${pathParamName}: "some sample value" } or ` +
|
||||
`it can be an "object" of the form { "${pathParamName}": { value: "some sample value", skipUrlEncoding: true } }.`
|
||||
);
|
||||
}
|
||||
|
||||
if (typeof pathParam.valueOf() === "string") {
|
||||
url = url.replace(item, encodeURIComponent(pathParam));
|
||||
}
|
||||
|
||||
if (typeof pathParam.valueOf() === "object") {
|
||||
if (!pathParam.value) {
|
||||
throw new Error(
|
||||
`options.pathParameters[${pathParamName}] is of type "object" but it does not contain a "value" property.`
|
||||
);
|
||||
}
|
||||
if (pathParam.skipUrlEncoding) {
|
||||
url = url.replace(item, pathParam.value);
|
||||
} else {
|
||||
url = url.replace(item, encodeURIComponent(pathParam.value));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
// append query parameters to the url if they are provided. They can be provided with pathTemplate or url option.
|
||||
if (options.queryParameters) {
|
||||
const queryParameters = options.queryParameters;
|
||||
if (typeof queryParameters !== "object") {
|
||||
throw new Error(
|
||||
`options.queryParameters must be of type object. It should be a JSON object ` +
|
||||
`of "query-parameter-name" as the key and the "query-parameter-value" as the value. ` +
|
||||
`The "query-parameter-value" may be fo type "string" or an "object" of the form { value: "query-parameter-value", skipUrlEncoding: true }.`
|
||||
);
|
||||
}
|
||||
// append question mark if it is not present in the url
|
||||
if (this.url && this.url.indexOf("?") === -1) {
|
||||
this.url += "?";
|
||||
}
|
||||
// construct queryString
|
||||
const queryParams = [];
|
||||
// We need to populate this.query as a dictionary if the request is being used for Sway's validateRequest().
|
||||
this.query = {};
|
||||
for (const queryParamName in queryParameters) {
|
||||
const queryParam: any = queryParameters[queryParamName];
|
||||
if (queryParam) {
|
||||
if (typeof queryParam === "string") {
|
||||
queryParams.push(queryParamName + "=" + encodeURIComponent(queryParam));
|
||||
this.query[queryParamName] = encodeURIComponent(queryParam);
|
||||
} else if (typeof queryParam === "object") {
|
||||
if (!queryParam.value) {
|
||||
throw new Error(
|
||||
`options.queryParameters[${queryParamName}] is of type "object" but it does not contain a "value" property.`
|
||||
);
|
||||
}
|
||||
if (queryParam.skipUrlEncoding) {
|
||||
queryParams.push(queryParamName + "=" + queryParam.value);
|
||||
this.query[queryParamName] = queryParam.value;
|
||||
} else {
|
||||
queryParams.push(queryParamName + "=" + encodeURIComponent(queryParam.value));
|
||||
this.query[queryParamName] = encodeURIComponent(queryParam.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // end-of-for
|
||||
// append the queryString
|
||||
this.url += queryParams.join("&");
|
||||
}
|
||||
|
||||
// add headers to the request if they are provided
|
||||
if (options.headers) {
|
||||
const headers = options.headers;
|
||||
for (const headerName of Object.keys(options.headers)) {
|
||||
this.headers.set(headerName, headers[headerName]);
|
||||
}
|
||||
}
|
||||
// ensure accept-language is set correctly
|
||||
if (!this.headers.get("accept-language")) {
|
||||
this.headers.set("accept-language", "en-US");
|
||||
}
|
||||
// ensure the request-id is set correctly
|
||||
if (!this.headers.get("x-ms-client-request-id") && !options.disableClientRequestId) {
|
||||
this.headers.set("x-ms-client-request-id", generateUuid());
|
||||
}
|
||||
|
||||
// default
|
||||
if (!this.headers.get("Content-Type")) {
|
||||
this.headers.set("Content-Type", "application/json; charset=utf-8");
|
||||
}
|
||||
|
||||
// set the request body. request.js automatically sets the Content-Length request header, so we need not set it explicilty
|
||||
this.body = options.body;
|
||||
if (options.body != undefined) {
|
||||
// body as a stream special case. set the body as-is and check for some special request headers specific to sending a stream.
|
||||
if (options.bodyIsStream) {
|
||||
if (!this.headers.get("Transfer-Encoding")) {
|
||||
this.headers.set("Transfer-Encoding", "chunked");
|
||||
}
|
||||
if (this.headers.get("Content-Type") !== "application/octet-stream") {
|
||||
this.headers.set("Content-Type", "application/octet-stream");
|
||||
}
|
||||
} else {
|
||||
if (options.serializationMapper) {
|
||||
this.body = new Serializer(options.mappers).serialize(
|
||||
options.serializationMapper,
|
||||
options.body,
|
||||
"requestBody"
|
||||
);
|
||||
}
|
||||
if (!options.disableJsonStringifyOnBody) {
|
||||
this.body = JSON.stringify(options.body);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.abortSignal = options.abortSignal;
|
||||
this.onDownloadProgress = options.onDownloadProgress;
|
||||
this.onUploadProgress = options.onUploadProgress;
|
||||
this.redirectLimit = options.redirectLimit;
|
||||
this.streamResponseBody = options.streamResponseBody;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clone this WebResource HTTP request object.
|
||||
* @returns {WebResource} The clone of this WebResource HTTP request object.
|
||||
*/
|
||||
clone(): WebResource {
|
||||
const result = new WebResource(
|
||||
this.url,
|
||||
this.method,
|
||||
this.body,
|
||||
this.query,
|
||||
this.headers && this.headers.clone(),
|
||||
this.streamResponseBody,
|
||||
this.withCredentials,
|
||||
this.abortSignal,
|
||||
this.timeout,
|
||||
this.onUploadProgress,
|
||||
this.onDownloadProgress,
|
||||
this.proxySettings,
|
||||
this.keepAlive,
|
||||
this.agentSettings,
|
||||
this.redirectLimit
|
||||
);
|
||||
|
||||
if (this.formData) {
|
||||
result.formData = this.formData;
|
||||
}
|
||||
|
||||
if (this.operationSpec) {
|
||||
result.operationSpec = this.operationSpec;
|
||||
}
|
||||
|
||||
if (this.shouldDeserialize) {
|
||||
result.shouldDeserialize = this.shouldDeserialize;
|
||||
}
|
||||
|
||||
if (this.operationResponseGetter) {
|
||||
result.operationResponseGetter = this.operationResponseGetter;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
export interface RequestPrepareOptions {
|
||||
/**
|
||||
* The HTTP request method. Valid values are "GET", "PUT", "HEAD", "DELETE", "OPTIONS", "POST",
|
||||
* or "PATCH".
|
||||
*/
|
||||
method: HttpMethods;
|
||||
/**
|
||||
* The request url. It may or may not have query parameters in it. Either provide the "url" or
|
||||
* provide the "pathTemplate" in the options object. Both the options are mutually exclusive.
|
||||
*/
|
||||
url?: string;
|
||||
/**
|
||||
* A dictionary of query parameters to be appended to the url, where
|
||||
* the "key" is the "query-parameter-name" and the "value" is the "query-parameter-value".
|
||||
* The "query-parameter-value" can be of type "string" or it can be of type "object".
|
||||
* The "object" format should be used when you want to skip url encoding. While using the object format,
|
||||
* the object must have a property named value which provides the "query-parameter-value".
|
||||
* Example:
|
||||
* - query-parameter-value in "object" format: { "query-parameter-name": { value: "query-parameter-value", skipUrlEncoding: true } }
|
||||
* - query-parameter-value in "string" format: { "query-parameter-name": "query-parameter-value"}.
|
||||
* Note: "If options.url already has some query parameters, then the value provided in options.queryParameters will be appended to the url.
|
||||
*/
|
||||
queryParameters?: { [key: string]: any | ParameterValue };
|
||||
/**
|
||||
* The path template of the request url. Either provide the "url" or provide the "pathTemplate" in
|
||||
* the options object. Both the options are mutually exclusive.
|
||||
* Example: "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Storage/storageAccounts/{accountName}"
|
||||
*/
|
||||
pathTemplate?: string;
|
||||
/**
|
||||
* The base url of the request. Default value is: "https://management.azure.com". This is
|
||||
* applicable only with pathTemplate. If you are providing options.url then it is expected that
|
||||
* you provide the complete url.
|
||||
*/
|
||||
baseUrl?: string;
|
||||
/**
|
||||
* A dictionary of path parameters that need to be replaced with actual values in the pathTemplate.
|
||||
* Here the key is the "path-parameter-name" and the value is the "path-parameter-value".
|
||||
* The "path-parameter-value" can be of type "string" or it can be of type "object".
|
||||
* The "object" format should be used when you want to skip url encoding. While using the object format,
|
||||
* the object must have a property named value which provides the "path-parameter-value".
|
||||
* Example:
|
||||
* - path-parameter-value in "object" format: { "path-parameter-name": { value: "path-parameter-value", skipUrlEncoding: true } }
|
||||
* - path-parameter-value in "string" format: { "path-parameter-name": "path-parameter-value" }.
|
||||
*/
|
||||
pathParameters?: { [key: string]: any | ParameterValue };
|
||||
formData?: { [key: string]: any };
|
||||
/**
|
||||
* A dictionary of request headers that need to be applied to the request.
|
||||
* Here the key is the "header-name" and the value is the "header-value". The header-value MUST be of type string.
|
||||
* - ContentType must be provided with the key name as "Content-Type". Default value "application/json; charset=utf-8".
|
||||
* - "Transfer-Encoding" is set to "chunked" by default if "options.bodyIsStream" is set to true.
|
||||
* - "Content-Type" is set to "application/octet-stream" by default if "options.bodyIsStream" is set to true.
|
||||
* - "accept-language" by default is set to "en-US"
|
||||
* - "x-ms-client-request-id" by default is set to a new Guid. To not generate a guid for the request, please set options.disableClientRequestId to true
|
||||
*/
|
||||
headers?: { [key: string]: any };
|
||||
/**
|
||||
* When set to true, instructs the client to not set "x-ms-client-request-id" header to a new Guid().
|
||||
*/
|
||||
disableClientRequestId?: boolean;
|
||||
/**
|
||||
* The request body. It can be of any type. This value will be serialized if it is not a stream.
|
||||
*/
|
||||
body?: any;
|
||||
/**
|
||||
* Provides information on how to serialize the request body.
|
||||
*/
|
||||
serializationMapper?: Mapper;
|
||||
/**
|
||||
* A dictionary of mappers that may be used while [de]serialization.
|
||||
*/
|
||||
mappers?: { [x: string]: any };
|
||||
/**
|
||||
* Provides information on how to deserialize the response body.
|
||||
*/
|
||||
deserializationMapper?: object;
|
||||
/**
|
||||
* Indicates whether this method should JSON.stringify() the request body. Default value: false.
|
||||
*/
|
||||
disableJsonStringifyOnBody?: boolean;
|
||||
/**
|
||||
* Indicates whether the request body is a stream (useful for file upload scenarios).
|
||||
*/
|
||||
bodyIsStream?: boolean;
|
||||
abortSignal?: AbortSignalLike;
|
||||
/**
|
||||
* Limit the number of redirects followed for this request. If set to 0, redirects will not be followed.
|
||||
* If left undefined the default redirect behaviour of the underlying node_fetch will apply.
|
||||
*/
|
||||
redirectLimit?: number;
|
||||
|
||||
onUploadProgress?: (progress: TransferProgressEvent) => void;
|
||||
onDownloadProgress?: (progress: TransferProgressEvent) => void;
|
||||
streamResponseBody?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* The Parameter value provided for path or query parameters in RequestPrepareOptions
|
||||
*/
|
||||
export interface ParameterValue {
|
||||
value: any;
|
||||
skipUrlEncoding: boolean;
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
/**
|
||||
* Describes the base structure of the options object that will be used in every operation.
|
||||
*/
|
||||
export interface RequestOptionsBase {
|
||||
/**
|
||||
* @property {object} [customHeaders] User defined custom request headers that
|
||||
* will be applied before the request is sent.
|
||||
*/
|
||||
customHeaders?: { [key: string]: string };
|
||||
|
||||
/**
|
||||
* The signal which can be used to abort requests.
|
||||
*/
|
||||
abortSignal?: AbortSignalLike;
|
||||
|
||||
/**
|
||||
* The number of milliseconds a request can take before automatically being terminated.
|
||||
*/
|
||||
timeout?: number;
|
||||
|
||||
/**
|
||||
* Callback which fires upon upload progress.
|
||||
*/
|
||||
onUploadProgress?: (progress: TransferProgressEvent) => void;
|
||||
|
||||
/**
|
||||
* Callback which fires upon download progress.
|
||||
*/
|
||||
onDownloadProgress?: (progress: TransferProgressEvent) => void;
|
||||
|
||||
[key: string]: any;
|
||||
}
|
178
node_modules/@azure/ms-rest-js/lib/xhrHttpClient.ts
generated
vendored
Normal file
178
node_modules/@azure/ms-rest-js/lib/xhrHttpClient.ts
generated
vendored
Normal file
|
@ -0,0 +1,178 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
import { HttpClient } from "./httpClient";
|
||||
import { HttpHeaders } from "./httpHeaders";
|
||||
import { WebResourceLike, TransferProgressEvent } from "./webResource";
|
||||
import { HttpOperationResponse } from "./httpOperationResponse";
|
||||
import { RestError } from "./restError";
|
||||
|
||||
/**
|
||||
* A HttpClient implementation that uses XMLHttpRequest to send HTTP requests.
|
||||
*/
|
||||
export class XhrHttpClient implements HttpClient {
|
||||
public sendRequest(request: WebResourceLike): Promise<HttpOperationResponse> {
|
||||
const xhr = new XMLHttpRequest();
|
||||
|
||||
if (request.agentSettings) {
|
||||
throw new Error("HTTP agent settings not supported in browser environment");
|
||||
}
|
||||
|
||||
if (request.proxySettings) {
|
||||
throw new Error("HTTP proxy is not supported in browser environment");
|
||||
}
|
||||
|
||||
const abortSignal = request.abortSignal;
|
||||
if (abortSignal) {
|
||||
const listener = () => {
|
||||
xhr.abort();
|
||||
};
|
||||
abortSignal.addEventListener("abort", listener);
|
||||
xhr.addEventListener("readystatechange", () => {
|
||||
if (xhr.readyState === XMLHttpRequest.DONE) {
|
||||
abortSignal.removeEventListener("abort", listener);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
addProgressListener(xhr.upload, request.onUploadProgress);
|
||||
addProgressListener(xhr, request.onDownloadProgress);
|
||||
|
||||
if (request.formData) {
|
||||
const formData = request.formData;
|
||||
const requestForm = new FormData();
|
||||
const appendFormValue = (key: string, value: any) => {
|
||||
if (value && value.hasOwnProperty("value") && value.hasOwnProperty("options")) {
|
||||
requestForm.append(key, value.value, value.options);
|
||||
} else {
|
||||
requestForm.append(key, value);
|
||||
}
|
||||
};
|
||||
for (const formKey of Object.keys(formData)) {
|
||||
const formValue = formData[formKey];
|
||||
if (Array.isArray(formValue)) {
|
||||
for (let j = 0; j < formValue.length; j++) {
|
||||
appendFormValue(formKey, formValue[j]);
|
||||
}
|
||||
} else {
|
||||
appendFormValue(formKey, formValue);
|
||||
}
|
||||
}
|
||||
|
||||
request.body = requestForm;
|
||||
request.formData = undefined;
|
||||
const contentType = request.headers.get("Content-Type");
|
||||
if (contentType && contentType.indexOf("multipart/form-data") !== -1) {
|
||||
// browser will automatically apply a suitable content-type header
|
||||
request.headers.remove("Content-Type");
|
||||
}
|
||||
}
|
||||
|
||||
xhr.open(request.method, request.url);
|
||||
xhr.timeout = request.timeout;
|
||||
xhr.withCredentials = request.withCredentials;
|
||||
for (const header of request.headers.headersArray()) {
|
||||
xhr.setRequestHeader(header.name, header.value);
|
||||
}
|
||||
xhr.responseType = request.streamResponseBody ? "blob" : "text";
|
||||
|
||||
// tslint:disable-next-line:no-null-keyword
|
||||
xhr.send(request.body === undefined ? null : request.body);
|
||||
|
||||
if (request.streamResponseBody) {
|
||||
return new Promise((resolve, reject) => {
|
||||
xhr.addEventListener("readystatechange", () => {
|
||||
// Resolve as soon as headers are loaded
|
||||
if (xhr.readyState === XMLHttpRequest.HEADERS_RECEIVED) {
|
||||
const blobBody = new Promise<Blob>((resolve, reject) => {
|
||||
xhr.addEventListener("load", () => {
|
||||
resolve(xhr.response);
|
||||
});
|
||||
rejectOnTerminalEvent(request, xhr, reject);
|
||||
});
|
||||
resolve({
|
||||
request,
|
||||
status: xhr.status,
|
||||
headers: parseHeaders(xhr),
|
||||
blobBody,
|
||||
});
|
||||
}
|
||||
});
|
||||
rejectOnTerminalEvent(request, xhr, reject);
|
||||
});
|
||||
} else {
|
||||
return new Promise(function (resolve, reject) {
|
||||
xhr.addEventListener("load", () =>
|
||||
resolve({
|
||||
request,
|
||||
status: xhr.status,
|
||||
headers: parseHeaders(xhr),
|
||||
bodyAsText: xhr.responseText,
|
||||
})
|
||||
);
|
||||
rejectOnTerminalEvent(request, xhr, reject);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function addProgressListener(
|
||||
xhr: XMLHttpRequestEventTarget,
|
||||
listener?: (progress: TransferProgressEvent) => void
|
||||
) {
|
||||
if (listener) {
|
||||
xhr.addEventListener("progress", (rawEvent) =>
|
||||
listener({
|
||||
loadedBytes: rawEvent.loaded,
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// exported locally for testing
|
||||
export function parseHeaders(xhr: XMLHttpRequest) {
|
||||
const responseHeaders = new HttpHeaders();
|
||||
const headerLines = xhr
|
||||
.getAllResponseHeaders()
|
||||
.trim()
|
||||
.split(/[\r\n]+/);
|
||||
for (const line of headerLines) {
|
||||
const index = line.indexOf(":");
|
||||
const headerName = line.slice(0, index);
|
||||
const headerValue = line.slice(index + 2);
|
||||
responseHeaders.set(headerName, headerValue);
|
||||
}
|
||||
return responseHeaders;
|
||||
}
|
||||
|
||||
function rejectOnTerminalEvent(
|
||||
request: WebResourceLike,
|
||||
xhr: XMLHttpRequest,
|
||||
reject: (err: any) => void
|
||||
) {
|
||||
xhr.addEventListener("error", () =>
|
||||
reject(
|
||||
new RestError(
|
||||
`Failed to send request to ${request.url}`,
|
||||
RestError.REQUEST_SEND_ERROR,
|
||||
undefined,
|
||||
request
|
||||
)
|
||||
)
|
||||
);
|
||||
xhr.addEventListener("abort", () =>
|
||||
reject(
|
||||
new RestError("The request was aborted", RestError.REQUEST_ABORTED_ERROR, undefined, request)
|
||||
)
|
||||
);
|
||||
xhr.addEventListener("timeout", () =>
|
||||
reject(
|
||||
new RestError(
|
||||
`timeout of ${xhr.timeout}ms exceeded`,
|
||||
RestError.REQUEST_SEND_ERROR,
|
||||
undefined,
|
||||
request
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue