зеркало из https://github.com/Azure/ms-rest-js.git
Initial commit
This commit is contained in:
Родитель
54fb56b756
Коммит
1636d476ea
|
@ -0,0 +1,37 @@
|
|||
*.bmp binary
|
||||
*.dll binary
|
||||
*.gif binary
|
||||
*.jpg binary
|
||||
*.png binary
|
||||
*.snk binary
|
||||
*.exe binary
|
||||
*.wmv binary
|
||||
*.mp4 binary
|
||||
*.ismv binary
|
||||
*.isma binary
|
||||
|
||||
*.ascx text
|
||||
*.cmd text
|
||||
*.config text
|
||||
*.cs text diff=csharp
|
||||
*.csproj text merge=union
|
||||
*.edmx text
|
||||
|
||||
*.htm text
|
||||
*.html text
|
||||
|
||||
*.json text eol=lf
|
||||
*.ts text eol=lf
|
||||
*.js text eol=lf
|
||||
|
||||
*.msbuild text
|
||||
*.nuspec text
|
||||
|
||||
*.resx text
|
||||
*.ruleset text
|
||||
*.StyleCop text
|
||||
*.targets text
|
||||
*.txt text
|
||||
*.xml text
|
||||
|
||||
*.sln text eol=crlf merge=union
|
|
@ -1,59 +1,86 @@
|
|||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
#### linux gitignore
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
*~
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
# KDE directory preferences
|
||||
.directory
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
# Linux trash folder which might appear on any partition or disk
|
||||
.Trash-*
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
/obj/*
|
||||
/node_modules
|
||||
.ntvs_analysis.dat
|
||||
.ntvs_analysis.*
|
||||
npm-debug.log
|
||||
tmp/*
|
||||
packages/*
|
||||
*.njsperf
|
||||
.vs/
|
||||
bin/*
|
||||
/.vscode/*
|
||||
ValidationTool.njsproj
|
||||
ValidationTool.sln
|
||||
.vscode/launch.json
|
||||
|
||||
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
#### win gitignore
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
# Windows image file caches
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
# Folder config file
|
||||
Desktop.ini
|
||||
|
||||
# Compiled binary addons (http://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
# Recycle Bin used on file shares
|
||||
$RECYCLE.BIN/
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
# Windows Installer files
|
||||
*.cab
|
||||
*.msi
|
||||
*.msm
|
||||
*.msp
|
||||
|
||||
# Typescript v1 declaration files
|
||||
typings/
|
||||
# Windows shortcuts
|
||||
*.lnk
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
#### osx gitignore
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
# Icon must end with two \r
|
||||
Icon
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variables file
|
||||
.env
|
||||
# Thumbnails
|
||||
._*
|
||||
|
||||
# Files that might appear in the root of a volume
|
||||
.DocumentRevisions-V100
|
||||
.fseventsd
|
||||
.Spotlight-V100
|
||||
.TemporaryItems
|
||||
.Trashes
|
||||
.VolumeIcon.icns
|
||||
|
||||
# Directories potentially created on remote AFP share
|
||||
.AppleDB
|
||||
.AppleDesktop
|
||||
Network Trash Folder
|
||||
Temporary Items
|
||||
.apdisk
|
||||
|
||||
node_modules
|
||||
|
||||
#### JetBrains
|
||||
.idea
|
||||
|
||||
# ignore code gen virtual env folder
|
||||
SdkCodeGen
|
||||
|
||||
output/*
|
||||
|
||||
# Typescript output
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
.vscode/
|
||||
node_modules/
|
||||
samples/
|
||||
test/
|
||||
.travis.yml
|
||||
.gitignore
|
||||
gulpfile.js
|
|
@ -0,0 +1,5 @@
|
|||
language: node_js
|
||||
sudo: false
|
||||
node_js:
|
||||
- "6"
|
||||
- "8"
|
20
README.md
20
README.md
|
@ -1,3 +1,23 @@
|
|||
# ms-rest-js
|
||||
|
||||
Runtime for isomorphic javascript libraries (that work in the browser and node.js environemnt) generated via [Autorest](https://github.com/Azure/Autorest).
|
||||
|
||||
## Requirements
|
||||
- node.js version > 6.x
|
||||
- npm install -g typescript
|
||||
|
||||
## Installation
|
||||
- After cloning the repo, execute `npm install`
|
||||
|
||||
## Execution
|
||||
|
||||
### node.js
|
||||
- Set the subscriptionId and token
|
||||
- Run `node samples/node-sample.js`
|
||||
|
||||
### In the browser
|
||||
- Set the subscriptionId and token and then run
|
||||
- Open index.html file in the browser. It should show the response from GET request on the storage account. From Chrome type Ctrl + Shift + I and you can see the logs in console.
|
||||
|
||||
# Contributing
|
||||
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
"use strict";
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const constants_1 = require("../util/constants");
|
||||
const HeaderConstants = constants_1.Constants.HeaderConstants;
|
||||
const DEFAULT_AUTHORIZATION_SCHEME = "Basic";
|
||||
/**
|
||||
* Creates a new BasicAuthenticationCredentials object.
|
||||
*
|
||||
* @constructor
|
||||
* @param {string} userName User name.
|
||||
* @param {string} password Password.
|
||||
* @param {string} [authorizationScheme] The authorization scheme.
|
||||
*/
|
||||
class BasicAuthenticationCredentials {
|
||||
constructor(userName, password, authorizationScheme = DEFAULT_AUTHORIZATION_SCHEME) {
|
||||
this.authorizationScheme = 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 {WebResource} The WebResource to be signed.
|
||||
* @returns {Promise<WebResource>} - The signed request object.
|
||||
*/
|
||||
signRequest(webResource) {
|
||||
const credentials = `${this.userName}:${this.password}`;
|
||||
const encodedCredentials = `${this.authorizationScheme} ${Buffer.from(credentials).toString("base64")}`;
|
||||
if (!webResource.headers)
|
||||
webResource.headers = {};
|
||||
webResource.headers[HeaderConstants.AUTHORIZATION] = encodedCredentials;
|
||||
return Promise.resolve(webResource);
|
||||
}
|
||||
}
|
||||
exports.BasicAuthenticationCredentials = BasicAuthenticationCredentials;
|
||||
//# sourceMappingURL=basicAuthenticationCredentials.js.map
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"basicAuthenticationCredentials.js","sourceRoot":"","sources":["../../../lib/credentials/basicAuthenticationCredentials.ts"],"names":[],"mappings":";AAAA,4DAA4D;AAC5D,+FAA+F;;AAE/F,iDAA8C;AAG9C,MAAM,eAAe,GAAG,qBAAS,CAAC,eAAe,CAAC;AAClD,MAAM,4BAA4B,GAAG,OAAO,CAAC;AAE7C;;;;;;;GAOG;AACH;IAIE,YAAY,QAAgB,EAAE,QAAgB,EAAE,sBAA8B,4BAA4B;QAD1G,wBAAmB,GAAW,4BAA4B,CAAC;QAEzD,EAAE,CAAC,CAAC,QAAQ,KAAK,IAAI,IAAI,QAAQ,KAAK,SAAS,IAAI,OAAO,QAAQ,CAAC,OAAO,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC;YAC1F,MAAM,IAAI,KAAK,CAAC,kEAAkE,CAAC,CAAC;QACtF,CAAC;QACD,EAAE,CAAC,CAAC,QAAQ,KAAK,IAAI,IAAI,QAAQ,KAAK,SAAS,IAAI,OAAO,QAAQ,CAAC,OAAO,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC;YAC1F,MAAM,IAAI,KAAK,CAAC,kEAAkE,CAAC,CAAC;QACtF,CAAC;QACD,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,mBAAmB,GAAG,mBAAmB,CAAC;IACjD,CAAC;IAED;;;;;OAKG;IACH,WAAW,CAAC,WAAwB;QAClC,MAAM,WAAW,GAAG,GAAG,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QACxD,MAAM,kBAAkB,GAAG,GAAG,IAAI,CAAC,mBAAmB,IAAI,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QACxG,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,OAAO,CAAC;YAAC,WAAW,CAAC,OAAO,GAAG,EAAE,CAAC;QACnD,WAAW,CAAC,OAAO,CAAC,eAAe,CAAC,aAAa,CAAC,GAAG,kBAAkB,CAAC;QACxE,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IACtC,CAAC;CACF;AA7BD,wEA6BC"}
|
|
@ -0,0 +1,5 @@
|
|||
"use strict";
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
//# sourceMappingURL=serviceClientCredentials.js.map
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"serviceClientCredentials.js","sourceRoot":"","sources":["../../../lib/credentials/serviceClientCredentials.ts"],"names":[],"mappings":";AAAA,4DAA4D;AAC5D,+FAA+F"}
|
|
@ -0,0 +1,38 @@
|
|||
"use strict";
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const constants_1 = require("../util/constants");
|
||||
const HeaderConstants = constants_1.Constants.HeaderConstants;
|
||||
const DEFAULT_AUTHORIZATION_SCHEME = "Bearer";
|
||||
/**
|
||||
* Creates a new TokenCredentials object.
|
||||
*
|
||||
* @constructor
|
||||
* @param {string} token The token.
|
||||
* @param {string} authorizationScheme The authorization scheme.
|
||||
*/
|
||||
class TokenCredentials {
|
||||
constructor(token, authorizationScheme = DEFAULT_AUTHORIZATION_SCHEME) {
|
||||
this.authorizationScheme = 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 {WebResource} The WebResource to be signed.
|
||||
* @return {Promise<WebResource>} The signed request object.
|
||||
*/
|
||||
signRequest(webResource) {
|
||||
if (!webResource.headers)
|
||||
webResource.headers = {};
|
||||
webResource.headers[HeaderConstants.AUTHORIZATION] = `${this.authorizationScheme} ${this.token}`;
|
||||
return Promise.resolve(webResource);
|
||||
}
|
||||
}
|
||||
exports.TokenCredentials = TokenCredentials;
|
||||
//# sourceMappingURL=tokenCredentials.js.map
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"tokenCredentials.js","sourceRoot":"","sources":["../../../lib/credentials/tokenCredentials.ts"],"names":[],"mappings":";AAAA,4DAA4D;AAC5D,+FAA+F;;AAE/F,iDAA8C;AAI9C,MAAM,eAAe,GAAG,qBAAS,CAAC,eAAe,CAAC;AAClD,MAAM,4BAA4B,GAAG,QAAQ,CAAC;AAE9C;;;;;;GAMG;AACH;IAIE,YAAY,KAAa,EAAE,sBAA8B,4BAA4B;QAFrF,wBAAmB,GAAW,4BAA4B,CAAC;QAGzD,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;YACX,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;QACxD,CAAC;QACD,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,mBAAmB,GAAG,mBAAmB,CAAC;IACjD,CAAC;IAED;;;;;OAKG;IACH,WAAW,CAAC,WAAwB;QAClC,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,OAAO,CAAC;YAAC,WAAW,CAAC,OAAO,GAAG,EAAE,CAAC;QACnD,WAAW,CAAC,OAAO,CAAC,eAAe,CAAC,aAAa,CAAC,GAAG,GAAG,IAAI,CAAC,mBAAmB,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QACjG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IACtC,CAAC;CACF;AAvBD,4CAuBC"}
|
|
@ -0,0 +1,15 @@
|
|||
"use strict";
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
class BaseFilter {
|
||||
constructor() { }
|
||||
before(request) {
|
||||
return Promise.resolve(request);
|
||||
}
|
||||
after(response) {
|
||||
return Promise.resolve(response);
|
||||
}
|
||||
}
|
||||
exports.BaseFilter = BaseFilter;
|
||||
//# sourceMappingURL=baseFilter.js.map
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"baseFilter.js","sourceRoot":"","sources":["../../../lib/filters/baseFilter.ts"],"names":[],"mappings":";AAAA,4DAA4D;AAC5D,+FAA+F;;AAK/F;IAEE,gBAAgB,CAAC;IAEjB,MAAM,CAAC,OAAoB;QACzB,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAClC,CAAC;IAED,KAAK,CAAC,QAA+B;QACnC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACnC,CAAC;CACF;AAXD,gCAWC"}
|
|
@ -0,0 +1,116 @@
|
|||
"use strict";
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const baseFilter_1 = require("./baseFilter");
|
||||
const utils = require("../util/utils");
|
||||
/**
|
||||
* @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.
|
||||
*/
|
||||
class ExponentialRetryPolicyFilter extends baseFilter_1.BaseFilter {
|
||||
constructor(retryCount, retryInterval, minRetryInterval, maxRetryInterval) {
|
||||
super();
|
||||
this.DEFAULT_CLIENT_RETRY_INTERVAL = 1000 * 30;
|
||||
this.DEFAULT_CLIENT_RETRY_COUNT = 3;
|
||||
this.DEFAULT_CLIENT_MAX_RETRY_INTERVAL = 1000 * 90;
|
||||
this.DEFAULT_CLIENT_MIN_RETRY_INTERVAL = 1000 * 3;
|
||||
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;
|
||||
}
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
shouldRetry(statusCode, retryData) {
|
||||
if ((statusCode < 500 && statusCode !== 408) || statusCode === 501 || statusCode === 505) {
|
||||
return false;
|
||||
}
|
||||
let currentCount;
|
||||
if (!retryData) {
|
||||
throw new Error("retryData for the ExponentialRetryPolicyFilter cannot be null.");
|
||||
}
|
||||
else {
|
||||
currentCount = (retryData && retryData.retryCount);
|
||||
}
|
||||
return (currentCount < this.retryCount);
|
||||
}
|
||||
/**
|
||||
* Updates the retry data for the next attempt.
|
||||
*
|
||||
* @param {RetryData} retryData The retry data.
|
||||
* @param {object} err The operation"s error, if any.
|
||||
*/
|
||||
updateRetryData(retryData, err) {
|
||||
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 = this.retryInterval * 0.8 +
|
||||
Math.floor(Math.random() * (this.retryInterval * 1.2 - this.retryInterval * 0.8));
|
||||
incrementDelta *= boundedRandDelta;
|
||||
retryData.retryInterval = Math.min(this.minRetryInterval + incrementDelta, this.maxRetryInterval);
|
||||
return retryData;
|
||||
}
|
||||
retry(operationResponse, retryData, err) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const self = this;
|
||||
const response = operationResponse.response;
|
||||
retryData = self.updateRetryData(retryData, err);
|
||||
if (!utils.objectIsNull(response) && self.shouldRetry(response.status, retryData)) {
|
||||
try {
|
||||
yield utils.delay(retryData.retryInterval);
|
||||
const res = yield utils.dispatchRequest(operationResponse.request);
|
||||
return self.retry(res, retryData, err);
|
||||
}
|
||||
catch (err) {
|
||||
return self.retry(operationResponse, retryData, err);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!utils.objectIsNull(err)) {
|
||||
// If the operation failed in the end, return all errors instead of just the last one
|
||||
err = retryData.error;
|
||||
return Promise.reject(err);
|
||||
}
|
||||
return Promise.resolve(operationResponse);
|
||||
}
|
||||
});
|
||||
}
|
||||
after(operationResponse) {
|
||||
return this.retry(operationResponse);
|
||||
}
|
||||
}
|
||||
exports.ExponentialRetryPolicyFilter = ExponentialRetryPolicyFilter;
|
||||
//# sourceMappingURL=exponentialRetryPolicyFilter.js.map
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"exponentialRetryPolicyFilter.js","sourceRoot":"","sources":["../../../lib/filters/exponentialRetryPolicyFilter.ts"],"names":[],"mappings":"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"}
|
|
@ -0,0 +1,21 @@
|
|||
"use strict";
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const baseFilter_1 = require("./baseFilter");
|
||||
class LogFilter extends baseFilter_1.BaseFilter {
|
||||
constructor(logger = console.log) {
|
||||
super();
|
||||
this.logger = logger;
|
||||
}
|
||||
after(operationResponse) {
|
||||
const self = this;
|
||||
self.logger(`>> Request: ${JSON.stringify(operationResponse.request, undefined, 2)}`);
|
||||
self.logger(`>> Response status code: ${operationResponse.response.status}`);
|
||||
const responseBody = operationResponse.bodyAsText;
|
||||
self.logger(`>> Body: ${responseBody}`);
|
||||
return Promise.resolve(operationResponse);
|
||||
}
|
||||
}
|
||||
exports.LogFilter = LogFilter;
|
||||
//# sourceMappingURL=logFilter.js.map
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"logFilter.js","sourceRoot":"","sources":["../../../lib/filters/logFilter.ts"],"names":[],"mappings":";AAAA,4DAA4D;AAC5D,+FAA+F;;AAE/F,6CAA0C;AAG1C,eAAuB,SAAQ,uBAAU;IAIvC,YAAY,SAAc,OAAO,CAAC,GAAG;QACnC,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED,KAAK,CAAC,iBAAwC;QAC5C,MAAM,IAAI,GAAG,IAAI,CAAC;QAClB,IAAI,CAAC,MAAM,CAAC,eAAe,IAAI,CAAC,SAAS,CAAC,iBAAiB,CAAC,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;QACtF,IAAI,CAAC,MAAM,CAAC,4BAA4B,iBAAiB,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;QAC7E,MAAM,YAAY,GAAG,iBAAiB,CAAC,UAAU,CAAC;QAClD,IAAI,CAAC,MAAM,CAAC,YAAY,YAAY,EAAE,CAAC,CAAC;QACxC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAC5C,CAAC;CACF;AAjBD,8BAiBC"}
|
|
@ -0,0 +1,52 @@
|
|||
"use strict";
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const baseFilter_1 = require("./baseFilter");
|
||||
const constants_1 = require("../util/constants");
|
||||
const os = require("os");
|
||||
const isNode = require("detect-node");
|
||||
const HeaderConstants = constants_1.Constants.HeaderConstants;
|
||||
class MsRestUserAgentFilter extends baseFilter_1.BaseFilter {
|
||||
constructor(userAgentInfo) {
|
||||
super();
|
||||
this.userAgentInfo = userAgentInfo;
|
||||
}
|
||||
tagRequest(request) {
|
||||
if (isNode) {
|
||||
const osInfo = `(${os.arch()}-${os.type()}-${os.release()})`;
|
||||
if (this.userAgentInfo.indexOf(osInfo) === -1) {
|
||||
this.userAgentInfo.unshift(osInfo);
|
||||
}
|
||||
const runtimeInfo = `Node/${process.version}`;
|
||||
if (this.userAgentInfo.indexOf(runtimeInfo) === -1) {
|
||||
this.userAgentInfo.unshift(runtimeInfo);
|
||||
}
|
||||
const nodeSDKSignature = `Azure-SDK-For-Node`;
|
||||
if (this.userAgentInfo.indexOf(nodeSDKSignature) === -1) {
|
||||
const azureRuntime = `ms-rest-azure`;
|
||||
let insertIndex = this.userAgentInfo.indexOf(azureRuntime);
|
||||
// insert after azureRuntime, otherwise, insert last.
|
||||
insertIndex = insertIndex < 0 ? this.userAgentInfo.length : insertIndex + 1;
|
||||
this.userAgentInfo.splice(insertIndex, 0, nodeSDKSignature);
|
||||
}
|
||||
if (!request.headers)
|
||||
request.headers = {};
|
||||
request.headers[HeaderConstants.USER_AGENT] = this.userAgentInfo.join(" ");
|
||||
}
|
||||
return Promise.resolve(request);
|
||||
}
|
||||
before(request) {
|
||||
const self = this;
|
||||
if (!request.headers)
|
||||
request.headers = {};
|
||||
if (!request.headers[HeaderConstants.USER_AGENT]) {
|
||||
return self.tagRequest(request);
|
||||
}
|
||||
else {
|
||||
return Promise.resolve(request);
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.MsRestUserAgentFilter = MsRestUserAgentFilter;
|
||||
//# sourceMappingURL=msRestUserAgentFilter.js.map
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"msRestUserAgentFilter.js","sourceRoot":"","sources":["../../../lib/filters/msRestUserAgentFilter.ts"],"names":[],"mappings":";AAAA,4DAA4D;AAC5D,+FAA+F;;AAE/F,6CAA0C;AAE1C,iDAA8C;AAC9C,yBAAyB;AAEzB,MAAM,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;AACtC,MAAM,eAAe,GAAG,qBAAS,CAAC,eAAe,CAAC;AAElD,2BAAmC,SAAQ,uBAAU;IAInD,YAAY,aAA4B;QACtC,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,aAAa,GAAG,aAAa,CAAC;IACrC,CAAC;IAED,UAAU,CAAC,OAAoB;QAC7B,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;YACX,MAAM,MAAM,GAAG,IAAI,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,OAAO,EAAE,GAAG,CAAC;YAC7D,EAAE,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC9C,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YACrC,CAAC;YAED,MAAM,WAAW,GAAG,QAAQ,OAAO,CAAC,OAAO,EAAE,CAAC;YAC9C,EAAE,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;gBACnD,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;YAC1C,CAAC;YAED,MAAM,gBAAgB,GAAG,oBAAoB,CAAC;YAC9C,EAAE,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;gBACxD,MAAM,YAAY,GAAG,eAAe,CAAC;gBAErC,IAAI,WAAW,GAAG,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;gBAC3D,qDAAqD;gBACrD,WAAW,GAAG,WAAW,GAAG,CAAC,GAAG,IAAI,CAAC,aAAa,CAAC,MAAM,GAAG,WAAW,GAAG,CAAC,CAAC;gBAC5E,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,EAAE,gBAAgB,CAAC,CAAC;YAC9D,CAAC;YACD,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC;gBAAC,OAAO,CAAC,OAAO,GAAG,EAAE,CAAC;YAC3C,OAAO,CAAC,OAAO,CAAC,eAAe,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC7E,CAAC;QACD,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAClC,CAAC;IAED,MAAM,CAAC,OAAoB;QACzB,MAAM,IAAI,GAAG,IAAI,CAAC;QAClB,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC;YAAC,OAAO,CAAC,OAAO,GAAG,EAAE,CAAC;QAC3C,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;YACjD,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;QAClC,CAAC;QAAC,IAAI,CAAC,CAAC;YACN,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAClC,CAAC;IACH,CAAC;CACF;AA7CD,sDA6CC"}
|
|
@ -0,0 +1,59 @@
|
|||
"use strict";
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
const baseFilter_1 = require("./baseFilter");
|
||||
const utils = require("../util/utils");
|
||||
const parse = require("url-parse");
|
||||
class RedirectFilter extends baseFilter_1.BaseFilter {
|
||||
constructor(maximumRetries = 20) {
|
||||
super();
|
||||
this.maximumRetries = maximumRetries;
|
||||
}
|
||||
handleRedirect(operationResponse, currentRetries) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const request = operationResponse.request;
|
||||
const response = operationResponse.response;
|
||||
if (response && response.headers && response.headers.get("location") &&
|
||||
(response.status === 300 || response.status === 307 || (response.status === 303 && request.method === "POST")) &&
|
||||
(!this.maximumRetries || currentRetries < this.maximumRetries)) {
|
||||
if (parse(response.headers.get("location")).hostname) {
|
||||
request.url = response.headers.get("location");
|
||||
}
|
||||
else {
|
||||
const urlObject = parse(request.url);
|
||||
urlObject.set("pathname", response.headers.get("location"));
|
||||
request.url = urlObject.href;
|
||||
}
|
||||
// POST request with Status code 303 should be converted into a
|
||||
// redirected GET request if the redirect url is present in the location header
|
||||
if (response.status === 303) {
|
||||
request.method = "GET";
|
||||
}
|
||||
let res;
|
||||
try {
|
||||
res = yield utils.dispatchRequest(request);
|
||||
currentRetries++;
|
||||
}
|
||||
catch (err) {
|
||||
return Promise.reject(err);
|
||||
}
|
||||
return this.handleRedirect(res, currentRetries);
|
||||
}
|
||||
return Promise.resolve(operationResponse);
|
||||
});
|
||||
}
|
||||
after(operationResponse) {
|
||||
return this.handleRedirect(operationResponse, 0);
|
||||
}
|
||||
}
|
||||
exports.RedirectFilter = RedirectFilter;
|
||||
//# sourceMappingURL=redirectFilter.js.map
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"redirectFilter.js","sourceRoot":"","sources":["../../../lib/filters/redirectFilter.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,4DAA4D;AAC5D,+FAA+F;AAC/F,6CAA0C;AAE1C,uCAAuC;AAEvC,MAAM,KAAK,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;AAEnC,oBAA4B,SAAQ,uBAAU;IAI5C,YAAY,cAAc,GAAG,EAAE;QAC7B,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,cAAc,GAAG,cAAc,CAAC;IACvC,CAAC;IAEK,cAAc,CAAC,iBAAwC,EAAE,cAAsB;;YACnF,MAAM,OAAO,GAAG,iBAAiB,CAAC,OAAO,CAAC;YAC1C,MAAM,QAAQ,GAAG,iBAAiB,CAAC,QAAQ,CAAC;YAC5C,EAAE,CAAC,CAAC,QAAQ,IAAI,QAAQ,CAAC,OAAO,IAAI,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC;gBAClE,CAAC,QAAQ,CAAC,MAAM,KAAK,GAAG,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,KAAK,GAAG,IAAI,OAAO,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC;gBAC9G,CAAC,CAAC,IAAI,CAAC,cAAc,IAAI,cAAc,GAAG,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;gBACjE,EAAE,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;oBACrD,OAAO,CAAC,GAAG,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAW,CAAC;gBAC3D,CAAC;gBAAC,IAAI,CAAC,CAAC;oBACN,MAAM,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;oBACrC,SAAS,CAAC,GAAG,CAAC,UAAU,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAW,CAAC,CAAC;oBACtE,OAAO,CAAC,GAAG,GAAG,SAAS,CAAC,IAAI,CAAC;gBAC/B,CAAC;gBACD,+DAA+D;gBAC/D,+EAA+E;gBAC/E,EAAE,CAAC,CAAC,QAAQ,CAAC,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC;oBAC5B,OAAO,CAAC,MAAM,GAAG,KAAK,CAAC;gBACzB,CAAC;gBACD,IAAI,GAA0B,CAAC;gBAC/B,IAAI,CAAC;oBACH,GAAG,GAAG,MAAM,KAAK,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;oBAC3C,cAAc,EAAE,CAAC;gBACnB,CAAC;gBAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;oBACb,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBAC7B,CAAC;gBACD,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;YAClD,CAAC;YACD,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC;QAC5C,CAAC;KAAA;IAED,KAAK,CAAC,iBAAwC;QAC5C,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,iBAAiB,EAAE,CAAC,CAAC,CAAC;IACnD,CAAC;CACF;AA1CD,wCA0CC"}
|
|
@ -0,0 +1,191 @@
|
|||
"use strict";
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
const baseFilter_1 = require("./baseFilter");
|
||||
const utils = require("../util/utils");
|
||||
let retryTimeout = 30;
|
||||
class RPRegistrationFilter extends baseFilter_1.BaseFilter {
|
||||
constructor(retryTimeout = 30) {
|
||||
super();
|
||||
retryTimeout = retryTimeout;
|
||||
}
|
||||
after(operationResponse) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
let rpName, urlPrefix;
|
||||
const options = operationResponse.request;
|
||||
if (operationResponse.response.status === 409) {
|
||||
rpName = this.checkRPNotRegisteredError(operationResponse.bodyAsText);
|
||||
}
|
||||
if (rpName) {
|
||||
urlPrefix = this.extractSubscriptionUrl(options.url);
|
||||
let registrationStatus = false;
|
||||
try {
|
||||
registrationStatus = yield this.registerRP(urlPrefix, rpName, options);
|
||||
}
|
||||
catch (err) {
|
||||
// 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.
|
||||
}
|
||||
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.
|
||||
options.headers["x-ms-client-request-id"] = utils.generateUuid();
|
||||
let finalRes;
|
||||
try {
|
||||
finalRes = yield utils.dispatchRequest(options);
|
||||
}
|
||||
catch (err) {
|
||||
return Promise.reject(err);
|
||||
}
|
||||
return Promise.resolve(finalRes);
|
||||
}
|
||||
}
|
||||
return Promise.resolve(operationResponse);
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Reuses the headers of the original request and url (if specified).
|
||||
* @param {WebResource} originalRequest The original request
|
||||
* @param {boolean} reuseUrlToo Should the url from the original request be reused as well. Default false.
|
||||
* @returns {object} reqOptions - A new request object with desired headers.
|
||||
*/
|
||||
getRequestEssentials(originalRequest, reuseUrlToo = false) {
|
||||
const reqOptions = {
|
||||
headers: {}
|
||||
};
|
||||
if (reuseUrlToo) {
|
||||
reqOptions.url = originalRequest.url;
|
||||
}
|
||||
// Copy over the original request headers. This will get us the auth token and other useful stuff from
|
||||
// the original request header. Thus making it easier to make requests from this filter.
|
||||
for (const h in originalRequest.headers) {
|
||||
reqOptions.headers[h] = originalRequest.headers[h];
|
||||
}
|
||||
// We have to change the x-ms-client-request-id otherwise Azure endpoint
|
||||
// will return the initial 409 (cached) response.
|
||||
reqOptions.headers["x-ms-client-request-id"] = utils.generateUuid();
|
||||
// Set content-type to application/json
|
||||
reqOptions.headers["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} result The name of the RP if condition is satisfied else undefined.
|
||||
*/
|
||||
checkRPNotRegisteredError(body) {
|
||||
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} urlPrefix The url prefix as explained above.
|
||||
*/
|
||||
extractSubscriptionUrl(url) {
|
||||
let result;
|
||||
const matchRes = url.match(/.*\/subscriptions\/[a-f0-9-]+\//ig);
|
||||
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 {string} urlPrefix - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/
|
||||
* @param {string} provider - The provider name to be registered.
|
||||
* @param {object} 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
|
||||
*/
|
||||
registerRP(urlPrefix, provider, originalRequest) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const postUrl = `${urlPrefix}providers/${provider}/register?api-version=2016-02-01`;
|
||||
const getUrl = `${urlPrefix}providers/${provider}?api-version=2016-02-01`;
|
||||
const reqOptions = this.getRequestEssentials(originalRequest);
|
||||
reqOptions.method = "POST";
|
||||
reqOptions.url = postUrl;
|
||||
let res;
|
||||
try {
|
||||
res = yield utils.dispatchRequest(reqOptions);
|
||||
}
|
||||
catch (err) {
|
||||
return Promise.reject(err);
|
||||
}
|
||||
if (res.response.status !== 200) {
|
||||
return Promise.reject(new Error(`Autoregistration of ${provider} failed. Please try registering manually.`));
|
||||
}
|
||||
let statusRes = false;
|
||||
try {
|
||||
statusRes = yield this.getRegistrationStatus(getUrl, originalRequest);
|
||||
}
|
||||
catch (err) {
|
||||
return Promise.reject(err);
|
||||
}
|
||||
return Promise.resolve(statusRes);
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 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 {string} url - The request url for polling
|
||||
* @param {object} 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>} promise - True if RP Registration is successful.
|
||||
*/
|
||||
getRegistrationStatus(url, originalRequest) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const reqOptions = this.getRequestEssentials(originalRequest);
|
||||
let res;
|
||||
let result = false;
|
||||
reqOptions.url = url;
|
||||
reqOptions.method = "GET";
|
||||
try {
|
||||
res = yield utils.dispatchRequest(reqOptions);
|
||||
}
|
||||
catch (err) {
|
||||
return Promise.reject(err);
|
||||
}
|
||||
const obj = res.bodyAsJson;
|
||||
if (res.bodyAsJson && obj.registrationState && obj.registrationState === "Registered") {
|
||||
result = true;
|
||||
}
|
||||
else {
|
||||
setTimeout(() => { return this.getRegistrationStatus(url, originalRequest); }, retryTimeout * 1000);
|
||||
}
|
||||
return Promise.resolve(result);
|
||||
});
|
||||
}
|
||||
}
|
||||
exports.RPRegistrationFilter = RPRegistrationFilter;
|
||||
//# sourceMappingURL=rpRegistrationFilter.js.map
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"rpRegistrationFilter.js","sourceRoot":"","sources":["../../../lib/filters/rpRegistrationFilter.ts"],"names":[],"mappings":"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"}
|
|
@ -0,0 +1,17 @@
|
|||
"use strict";
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const baseFilter_1 = require("./baseFilter");
|
||||
class SigningFilter extends baseFilter_1.BaseFilter {
|
||||
constructor(authenticationProvider) {
|
||||
super();
|
||||
this.authenticationProvider = authenticationProvider;
|
||||
}
|
||||
before(request) {
|
||||
const self = this;
|
||||
return self.authenticationProvider.signRequest(request);
|
||||
}
|
||||
}
|
||||
exports.SigningFilter = SigningFilter;
|
||||
//# sourceMappingURL=signingFilter.js.map
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"signingFilter.js","sourceRoot":"","sources":["../../../lib/filters/signingFilter.ts"],"names":[],"mappings":";AAAA,4DAA4D;AAC5D,+FAA+F;;AAE/F,6CAA0C;AAI1C,mBAA2B,SAAQ,uBAAU;IAI3C,YAAY,sBAAgD;QAC1D,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,sBAAsB,GAAG,sBAAsB,CAAC;IACvD,CAAC;IAED,MAAM,CAAC,OAAoB;QACzB,MAAM,IAAI,GAAG,IAAI,CAAC;QAClB,MAAM,CAAC,IAAI,CAAC,sBAAsB,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;IAC1D,CAAC;CACF;AAbD,sCAaC"}
|
|
@ -0,0 +1,115 @@
|
|||
"use strict";
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const baseFilter_1 = require("./baseFilter");
|
||||
const utils = require("../util/utils");
|
||||
/**
|
||||
* @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.
|
||||
*/
|
||||
class SystemErrorRetryPolicyFilter extends baseFilter_1.BaseFilter {
|
||||
constructor(retryCount, retryInterval, minRetryInterval, maxRetryInterval) {
|
||||
super();
|
||||
this.DEFAULT_CLIENT_RETRY_INTERVAL = 1000 * 30;
|
||||
this.DEFAULT_CLIENT_RETRY_COUNT = 3;
|
||||
this.DEFAULT_CLIENT_MAX_RETRY_INTERVAL = 1000 * 90;
|
||||
this.DEFAULT_CLIENT_MIN_RETRY_INTERVAL = 1000 * 3;
|
||||
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;
|
||||
}
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
shouldRetry(retryData) {
|
||||
let currentCount;
|
||||
if (!retryData) {
|
||||
throw new Error("retryData for the SystemErrorRetryPolicyFilter cannot be null.");
|
||||
}
|
||||
else {
|
||||
currentCount = (retryData && retryData.retryCount);
|
||||
}
|
||||
return (currentCount < this.retryCount);
|
||||
}
|
||||
/**
|
||||
* Updates the retry data for the next attempt.
|
||||
*
|
||||
* @param {RetryData} retryData The retry data.
|
||||
* @param {object} err The operation"s error, if any.
|
||||
*/
|
||||
updateRetryData(retryData, err) {
|
||||
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 = this.retryInterval * 0.8 +
|
||||
Math.floor(Math.random() * (this.retryInterval * 1.2 - this.retryInterval * 0.8));
|
||||
incrementDelta *= boundedRandDelta;
|
||||
retryData.retryInterval = Math.min(this.minRetryInterval + incrementDelta, this.maxRetryInterval);
|
||||
return retryData;
|
||||
}
|
||||
retry(operationResponse, retryData, err) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const self = this;
|
||||
retryData = self.updateRetryData(retryData, err);
|
||||
if (err && err.code && self.shouldRetry(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 {
|
||||
yield utils.delay(retryData.retryInterval);
|
||||
const res = yield utils.dispatchRequest(operationResponse.request);
|
||||
return self.retry(res, retryData, err);
|
||||
}
|
||||
catch (err) {
|
||||
return self.retry(operationResponse, retryData, err);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!utils.objectIsNull(err)) {
|
||||
// If the operation failed in the end, return all errors instead of just the last one
|
||||
err = retryData.error;
|
||||
return Promise.reject(err);
|
||||
}
|
||||
return Promise.resolve(operationResponse);
|
||||
}
|
||||
});
|
||||
}
|
||||
after(operationResponse) {
|
||||
return this.retry(operationResponse); // See: https://github.com/Microsoft/TypeScript/issues/7426
|
||||
}
|
||||
}
|
||||
exports.SystemErrorRetryPolicyFilter = SystemErrorRetryPolicyFilter;
|
||||
//# sourceMappingURL=systemErrorRetryPolicyFilter.js.map
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"systemErrorRetryPolicyFilter.js","sourceRoot":"","sources":["../../../lib/filters/systemErrorRetryPolicyFilter.ts"],"names":[],"mappings":"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"}
|
|
@ -0,0 +1,36 @@
|
|||
"use strict";
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
/**
|
||||
* Wrapper object for http request and response. Deserialized object is stored in
|
||||
* the `body` property.
|
||||
* @class
|
||||
* Initializes a new instance of the HttpOperationResponse class.
|
||||
* @constructor
|
||||
*/
|
||||
class HttpOperationResponse {
|
||||
constructor(request, response, body) {
|
||||
/**
|
||||
* Reference to the original request object.
|
||||
* [WebResource] object.
|
||||
* @type {object}
|
||||
*/
|
||||
this.request = request;
|
||||
/**
|
||||
* Reference to the original response object.
|
||||
* [ServerResponse] object.
|
||||
* @type {object}
|
||||
*/
|
||||
this.response = response;
|
||||
/**
|
||||
* The response object.
|
||||
* @type {object}
|
||||
*/
|
||||
this.bodyAsStream = body;
|
||||
this.bodyAsText = null;
|
||||
this.bodyAsJson = null;
|
||||
}
|
||||
}
|
||||
exports.HttpOperationResponse = HttpOperationResponse;
|
||||
//# sourceMappingURL=httpOperationResponse.js.map
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"httpOperationResponse.js","sourceRoot":"","sources":["../../lib/httpOperationResponse.ts"],"names":[],"mappings":";AAAA,4DAA4D;AAC5D,+FAA+F;;AAI/F;;;;;;GAMG;AACH;IAsBE,YAAY,OAAoB,EAAE,QAAkB,EAAE,IAA2B;QAC/E;;;;WAIG;QACH,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QAEvB;;;;WAIG;QACH,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QAEzB;;;WAGG;QACH,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;QACzB,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACvB,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;IACzB,CAAC;CACF;AA7CD,sDA6CC"}
|
|
@ -0,0 +1,53 @@
|
|||
"use strict";
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const webResource_1 = require("./webResource");
|
||||
exports.WebResource = webResource_1.WebResource;
|
||||
const httpOperationResponse_1 = require("./httpOperationResponse");
|
||||
exports.HttpOperationResponse = httpOperationResponse_1.HttpOperationResponse;
|
||||
const restError_1 = require("./restError");
|
||||
exports.RestError = restError_1.RestError;
|
||||
const serviceClient_1 = require("./serviceClient");
|
||||
exports.ServiceClient = serviceClient_1.ServiceClient;
|
||||
const constants_1 = require("./util/constants");
|
||||
exports.Constants = constants_1.Constants;
|
||||
const requestPipeline_1 = require("./requestPipeline");
|
||||
exports.RequestPipeline = requestPipeline_1.RequestPipeline;
|
||||
const logFilter_1 = require("./filters/logFilter");
|
||||
exports.LogFilter = logFilter_1.LogFilter;
|
||||
const baseFilter_1 = require("./filters/baseFilter");
|
||||
exports.BaseFilter = baseFilter_1.BaseFilter;
|
||||
const exponentialRetryPolicyFilter_1 = require("./filters/exponentialRetryPolicyFilter");
|
||||
exports.ExponentialRetryPolicyFilter = exponentialRetryPolicyFilter_1.ExponentialRetryPolicyFilter;
|
||||
const systemErrorRetryPolicyFilter_1 = require("./filters/systemErrorRetryPolicyFilter");
|
||||
exports.SystemErrorRetryPolicyFilter = systemErrorRetryPolicyFilter_1.SystemErrorRetryPolicyFilter;
|
||||
const redirectFilter_1 = require("./filters/redirectFilter");
|
||||
exports.RedirectFilter = redirectFilter_1.RedirectFilter;
|
||||
const signingFilter_1 = require("./filters/signingFilter");
|
||||
exports.SigningFilter = signingFilter_1.SigningFilter;
|
||||
const msRestUserAgentFilter_1 = require("./filters/msRestUserAgentFilter");
|
||||
exports.MsRestUserAgentFilter = msRestUserAgentFilter_1.MsRestUserAgentFilter;
|
||||
const serializer_1 = require("./serializer");
|
||||
exports.MapperType = serializer_1.MapperType;
|
||||
exports.Serializer = serializer_1.Serializer;
|
||||
exports.serializeObject = serializer_1.serializeObject;
|
||||
const utils_1 = require("./util/utils");
|
||||
exports.stripRequest = utils_1.stripRequest;
|
||||
exports.stripResponse = utils_1.stripResponse;
|
||||
exports.delay = utils_1.delay;
|
||||
exports.executePromisesSequentially = utils_1.executePromisesSequentially;
|
||||
exports.generateUuid = utils_1.generateUuid;
|
||||
exports.encodeUri = utils_1.encodeUri;
|
||||
exports.promiseToCallback = utils_1.promiseToCallback;
|
||||
exports.promiseToServiceCallback = utils_1.promiseToServiceCallback;
|
||||
exports.isValidUuid = utils_1.isValidUuid;
|
||||
exports.dispatchRequest = utils_1.dispatchRequest;
|
||||
// Credentials
|
||||
const tokenCredentials_1 = require("./credentials/tokenCredentials");
|
||||
exports.TokenCredentials = tokenCredentials_1.TokenCredentials;
|
||||
const basicAuthenticationCredentials_1 = require("./credentials/basicAuthenticationCredentials");
|
||||
exports.BasicAuthenticationCredentials = basicAuthenticationCredentials_1.BasicAuthenticationCredentials;
|
||||
const isStream = require("is-stream");
|
||||
exports.isStream = isStream;
|
||||
//# sourceMappingURL=msRest.js.map
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"msRest.js","sourceRoot":"","sources":["../../lib/msRest.ts"],"names":[],"mappings":";AAAA,4DAA4D;AAC5D,+FAA+F;;AAE/F,+CAAoH;AAiClH,sBAjCO,yBAAW,CAiCP;AAhCb,mEAAgE;AAgCG,gCAhC1D,6CAAqB,CAgC0D;AA/BxF,2CAAwC;AAkCA,oBAlC/B,qBAAS,CAkC+B;AAjCjD,mDAAsE;AA8BoB,wBA9BjF,6BAAa,CA8BiF;AA7BvG,gDAA6C;AA6B4D,oBA7BhG,qBAAS,CA6BgG;AA5BlH,uDAAqE;AA4B+C,0BA5B3G,iCAAe,CA4B2G;AA3BnI,mDAAgD;AA4BwB,oBA5B/D,qBAAS,CA4B+D;AA3BjF,qDAAkD;AA2BU,qBA3BnD,uBAAU,CA2BmD;AA1BtE,yFAAsF;AA0BmB,uCA1BhG,2DAA4B,CA0BgG;AAzBrI,yFAAsF;AA0BpF,uCA1BO,2DAA4B,CA0BP;AAzB9B,6DAA0D;AA2BH,yBA3B9C,+BAAc,CA2B8C;AA1BrE,2DAAwD;AAwBxB,wBAxBvB,6BAAa,CAwBuB;AAvB7C,2EAAwE;AAuBzB,gCAvBtC,6CAAqB,CAuBsC;AAtBpE,6CAIsB;AAcsE,qBAhBvE,uBAAU,CAgBuE;AACvC,qBAhB7C,uBAAU,CAgB6C;AAAE,0BAhB1B,4BAAe,CAgB0B;AAd1F,wCAIsB;AAagD,uBAhBpE,oBAAY,CAgBoE;AAAE,wBAhBpE,qBAAa,CAgBoE;AAAE,gBAhBpE,aAAK,CAgBoE;AAAE,sCAfxG,mCAA2B,CAewG;AACnI,uBAhB6B,oBAAY,CAgB7B;AAAe,oBAhBgB,iBAAS,CAgBhB;AAAmE,4BAfvG,yBAAiB,CAeuG;AACxH,mCAhBmB,gCAAwB,CAgBnB;AADV,sBAf+B,mBAAW,CAe/B;AACW,0BAhBsB,uBAAe,CAgBtB;AAbrD,cAAc;AACd,qEAAkE;AAO0B,2BAPnF,mCAAgB,CAOmF;AAN5G,iGAA8F;AAQ5F,yCARO,+DAA8B,CAQP;AANhC,sCAAsC;AASV,4BAAQ"}
|
|
@ -0,0 +1,51 @@
|
|||
"use strict";
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const utils = require("./util/utils");
|
||||
class RequestPipeline {
|
||||
constructor(filters, requestOptions) {
|
||||
this.filters = filters || [];
|
||||
this.requestOptions = requestOptions || {};
|
||||
}
|
||||
addFilter(f) {
|
||||
this.filters.push(f);
|
||||
return;
|
||||
}
|
||||
create() {
|
||||
const self = this;
|
||||
let pipeline = [];
|
||||
if (self.filters && self.filters.length) {
|
||||
const beforeFilters = [];
|
||||
const afterFilters = [];
|
||||
for (let i = 0; i < self.filters.length; i++) {
|
||||
const filter = self.filters[i];
|
||||
if (filter.before && typeof filter.before === "function") {
|
||||
beforeFilters.push(filter.before.bind(filter));
|
||||
}
|
||||
if (filter.after && typeof filter.after === "function") {
|
||||
afterFilters.push(filter.after.bind(filter));
|
||||
}
|
||||
} // end-of-for-loop
|
||||
// add the request sink
|
||||
beforeFilters.push(self.requestSink.bind(self));
|
||||
pipeline = beforeFilters.concat(afterFilters);
|
||||
}
|
||||
else {
|
||||
pipeline.push(self.requestSink.bind(self));
|
||||
}
|
||||
const requestFun = (request) => {
|
||||
if (!request.headers)
|
||||
request.headers = {};
|
||||
return utils.executePromisesSequentially(pipeline, request);
|
||||
};
|
||||
return requestFun;
|
||||
}
|
||||
requestSink(options) {
|
||||
if (this.requestOptions.method)
|
||||
delete this.requestOptions.method;
|
||||
return utils.dispatchRequest(options);
|
||||
}
|
||||
}
|
||||
exports.RequestPipeline = RequestPipeline;
|
||||
//# sourceMappingURL=requestPipeline.js.map
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"requestPipeline.js","sourceRoot":"","sources":["../../lib/requestPipeline.ts"],"names":[],"mappings":";AAAA,4DAA4D;AAC5D,+FAA+F;;AAK/F,sCAAsC;AAKtC;IAIE,YAAY,OAAsB,EAAE,cAA4B;QAC9D,IAAI,CAAC,OAAO,GAAG,OAAO,IAAI,EAAE,CAAC;QAC7B,IAAI,CAAC,cAAc,GAAG,cAAc,IAAI,EAAE,CAAC;IAC7C,CAAC;IAED,SAAS,CAAC,CAAa;QACrB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACrB,MAAM,CAAC;IACT,CAAC;IAED,MAAM;QACJ,MAAM,IAAI,GAAG,IAAI,CAAC;QAClB,IAAI,QAAQ,GAAoB,EAAE,CAAC;QACnC,EAAE,CAAC,CAAC,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;YACxC,MAAM,aAAa,GAAoB,EAAE,CAAC;YAC1C,MAAM,YAAY,GAAoB,EAAE,CAAC;YACzC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC7C,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;gBAC/B,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM,IAAI,OAAO,MAAM,CAAC,MAAM,KAAK,UAAU,CAAC,CAAC,CAAC;oBACzD,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;gBACjD,CAAC;gBACD,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,IAAI,OAAO,MAAM,CAAC,KAAK,KAAK,UAAU,CAAC,CAAC,CAAC;oBACvD,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;gBAC/C,CAAC;YACH,CAAC,CAAA,kBAAkB;YACnB,uBAAuB;YACvB,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;YAChD,QAAQ,GAAG,aAAa,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;QAChD,CAAC;QAAC,IAAI,CAAC,CAAC;YACN,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QAC7C,CAAC;QACD,MAAM,UAAU,GAAoB,CAAC,OAAoB;YACvD,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC;gBAAC,OAAO,CAAC,OAAO,GAAG,EAAE,CAAC;YAC3C,MAAM,CAAC,KAAK,CAAC,2BAA2B,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAC9D,CAAC,CAAC;QACF,MAAM,CAAC,UAAU,CAAC;IACpB,CAAC;IAED,WAAW,CAAC,OAAoB;QAC9B,EAAE,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC;YAAC,OAAO,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC;QAClE,MAAM,CAAC,KAAK,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;IACxC,CAAC;CACF;AA9CD,0CA8CC"}
|
|
@ -0,0 +1,16 @@
|
|||
"use strict";
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
class RestError extends Error {
|
||||
constructor(message, code, statusCode, request, response, body) {
|
||||
super(message);
|
||||
this.code = code;
|
||||
this.statusCode = statusCode;
|
||||
this.request = request;
|
||||
this.response = response;
|
||||
this.body = body;
|
||||
}
|
||||
}
|
||||
exports.RestError = RestError;
|
||||
//# sourceMappingURL=restError.js.map
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"restError.js","sourceRoot":"","sources":["../../lib/restError.ts"],"names":[],"mappings":";AAAA,4DAA4D;AAC5D,+FAA+F;;AAI/F,eAAuB,SAAQ,KAAK;IAMlC,YAAY,OAAe,EAAE,IAAa,EAAE,UAAmB,EAAE,OAAqB,EAAE,QAAmB,EAAE,IAAU;QACrH,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF;AAdD,8BAcC"}
|
|
@ -0,0 +1,703 @@
|
|||
"use strict";
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const utils = require("./util/utils");
|
||||
const moment_1 = require("moment");
|
||||
const isBuffer = require("is-buffer");
|
||||
const isStream = require("is-stream");
|
||||
class Serializer {
|
||||
constructor(mappers) {
|
||||
this.modelMappers = mappers;
|
||||
}
|
||||
validateConstraints(mapper, value, objectName) {
|
||||
if (mapper.constraints && (value !== null || value !== undefined)) {
|
||||
Object.keys(mapper.constraints).forEach((constraintType) => {
|
||||
if (constraintType.match(/^ExclusiveMaximum$/ig) !== null) {
|
||||
if (value >= mapper.constraints.ExclusiveMaximum) {
|
||||
throw new Error(`"${objectName}" with value "${value}" should satify the constraint "ExclusiveMaximum": ${mapper.constraints.ExclusiveMaximum}.`);
|
||||
}
|
||||
}
|
||||
else if (constraintType.match(/^ExclusiveMinimum$/ig) !== null) {
|
||||
if (value <= mapper.constraints.ExclusiveMinimum) {
|
||||
throw new Error(`${objectName} " with value "${value} " should satify the constraint "ExclusiveMinimum": ${mapper.constraints.ExclusiveMinimum}.`);
|
||||
}
|
||||
}
|
||||
else if (constraintType.match(/^InclusiveMaximum$/ig) !== null) {
|
||||
if (value > mapper.constraints.InclusiveMaximum) {
|
||||
throw new Error(`${objectName}" with value "${value}" should satify the constraint "InclusiveMaximum": ${mapper.constraints.InclusiveMaximum}.`);
|
||||
}
|
||||
}
|
||||
else if (constraintType.match(/^InclusiveMinimum$/ig) !== null) {
|
||||
if (value < mapper.constraints.InclusiveMinimum) {
|
||||
throw new Error(`${objectName}" with value "${value}" should satify the constraint "InclusiveMinimum": ${mapper.constraints.InclusiveMinimum}.`);
|
||||
}
|
||||
}
|
||||
else if (constraintType.match(/^MaxItems$/ig) !== null) {
|
||||
if (value.length > mapper.constraints.MaxItems) {
|
||||
throw new Error(`${objectName}" with value "${value}" should satify the constraint "MaxItems": ${mapper.constraints.MaxItems}.`);
|
||||
}
|
||||
}
|
||||
else if (constraintType.match(/^MaxLength$/ig) !== null) {
|
||||
if (value.length > mapper.constraints.MaxLength) {
|
||||
throw new Error(`${objectName}" with value "${value}" should satify the constraint "MaxLength": ${mapper.constraints.MaxLength}.`);
|
||||
}
|
||||
}
|
||||
else if (constraintType.match(/^MinItems$/ig) !== null) {
|
||||
if (value.length < mapper.constraints.MinItems) {
|
||||
throw new Error(`${objectName}" with value "${value}" should satify the constraint "MinItems": ${mapper.constraints.MinItems}.`);
|
||||
}
|
||||
}
|
||||
else if (constraintType.match(/^MinLength$/ig) !== null) {
|
||||
if (value.length < mapper.constraints.MinLength) {
|
||||
throw new Error(`${objectName}" with value "${value}" should satify the constraint "MinLength": ${mapper.constraints.MinLength}.`);
|
||||
}
|
||||
}
|
||||
else if (constraintType.match(/^MultipleOf$/ig) !== null) {
|
||||
if (value.length % mapper.constraints.MultipleOf !== 0) {
|
||||
throw new Error(`${objectName}" with value "${value}" should satify the constraint "MultipleOf": ${mapper.constraints.MultipleOf}.`);
|
||||
}
|
||||
}
|
||||
else if (constraintType.match(/^Pattern$/ig) !== null) {
|
||||
if (value.match(mapper.constraints.Pattern.split("/").join("\/")) === null) {
|
||||
throw new Error(`${objectName}" with value "${value}" should satify the constraint "Pattern": ${mapper.constraints.Pattern}.`);
|
||||
}
|
||||
}
|
||||
else if (constraintType.match(/^UniqueItems/ig) !== null) {
|
||||
if (mapper.constraints.UniqueItems) {
|
||||
if (value.length !== value.filter((item, i, ar) => { {
|
||||
return ar.indexOf(item) === i;
|
||||
} }).length) {
|
||||
throw new Error(`${objectName}" with value "${value}" should satify the constraint "UniqueItems": ${mapper.constraints.UniqueItems}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
trimEnd(str, ch) {
|
||||
let len = str.length;
|
||||
while ((len - 1) >= 0 && str[len - 1] === ch) {
|
||||
--len;
|
||||
}
|
||||
return str.substr(0, len);
|
||||
}
|
||||
bufferToBase64Url(buffer) {
|
||||
if (!buffer) {
|
||||
return undefined;
|
||||
}
|
||||
if (!isBuffer(buffer)) {
|
||||
throw new Error(`Please provide an input of type Buffer for converting to Base64Url.`);
|
||||
}
|
||||
// Buffer to Base64.
|
||||
const str = buffer.toString("base64");
|
||||
// Base64 to Base64Url.
|
||||
return this.trimEnd(str, "=").replace(/\+/g, "-").replace(/\//g, "_");
|
||||
}
|
||||
base64UrlToBuffer(str) {
|
||||
if (!str) {
|
||||
return undefined;
|
||||
}
|
||||
if (str && typeof str.valueOf() !== "string") {
|
||||
throw new Error("Please provide an input of type string for converting to Buffer");
|
||||
}
|
||||
// Base64Url to Base64.
|
||||
str = str.replace(/\-/g, "+").replace(/\_/g, "/");
|
||||
// Base64 to Buffer.
|
||||
return Buffer.from(str, "base64");
|
||||
}
|
||||
splitSerializeName(prop) {
|
||||
const classes = [];
|
||||
let partialclass = "";
|
||||
const subwords = prop.split(".");
|
||||
subwords.forEach((item) => {
|
||||
if (item.charAt(item.length - 1) === "\\") {
|
||||
partialclass += item.substr(0, item.length - 1) + ".";
|
||||
}
|
||||
else {
|
||||
partialclass += item;
|
||||
classes.push(partialclass);
|
||||
partialclass = "";
|
||||
}
|
||||
});
|
||||
return classes;
|
||||
}
|
||||
dateToUnixTime(d) {
|
||||
if (!d) {
|
||||
return undefined;
|
||||
}
|
||||
if (typeof d.valueOf() === "string") {
|
||||
d = new Date(d);
|
||||
}
|
||||
return Math.floor(d.getTime() / 1000);
|
||||
}
|
||||
unixTimeToDate(n) {
|
||||
if (!n) {
|
||||
return undefined;
|
||||
}
|
||||
return new Date(n * 1000);
|
||||
}
|
||||
serializeBasicTypes(typeName, objectName, value) {
|
||||
if (value !== null && value !== undefined) {
|
||||
if (typeName.match(/^Number$/ig) !== null) {
|
||||
if (typeof value !== "number") {
|
||||
throw new Error(`${objectName} with value ${value} must be of type number.`);
|
||||
}
|
||||
}
|
||||
else if (typeName.match(/^String$/ig) !== null) {
|
||||
if (typeof value.valueOf() !== "string") {
|
||||
throw new Error(`${objectName} with value "${value}" must be of type string.`);
|
||||
}
|
||||
}
|
||||
else if (typeName.match(/^Uuid$/ig) !== null) {
|
||||
if (!(typeof value.valueOf() === "string" && utils.isValidUuid(value))) {
|
||||
throw new Error(`${objectName} with value "${value}" must be of type string and a valid uuid.`);
|
||||
}
|
||||
}
|
||||
else if (typeName.match(/^Boolean$/ig) !== null) {
|
||||
if (typeof value !== "boolean") {
|
||||
throw new Error(`${objectName} with value ${value} must be of type boolean.`);
|
||||
}
|
||||
}
|
||||
else if (typeName.match(/^Object$/ig) !== null) {
|
||||
if (typeof value !== "object") {
|
||||
throw new Error(`${objectName} must be of type object.`);
|
||||
}
|
||||
}
|
||||
else if (typeName.match(/^Stream$/ig) !== null) {
|
||||
if (!isStream(value)) {
|
||||
throw new Error(`${objectName} must be of type stream.`);
|
||||
}
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
serializeEnumType(objectName, allowedValues, value) {
|
||||
if (!allowedValues) {
|
||||
throw new Error(`Please provide a set of allowedValues to validate ${objectName} as an Enum Type.`);
|
||||
}
|
||||
const isPresent = allowedValues.some((item) => {
|
||||
if (typeof item.valueOf() === "string") {
|
||||
return item.toLowerCase() === value.toLowerCase();
|
||||
}
|
||||
return item === value;
|
||||
});
|
||||
if (!isPresent) {
|
||||
throw new Error(`${value} is not a valid value for ${objectName}. The valid values are: ${JSON.stringify(allowedValues)}.`);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
serializeBufferType(objectName, value) {
|
||||
if (value !== null && value !== undefined) {
|
||||
if (!isBuffer(value)) {
|
||||
throw new Error(`${objectName} must be of type Buffer.`);
|
||||
}
|
||||
value = value.toString("base64");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
serializeBase64UrlType(objectName, value) {
|
||||
if (value !== null && value !== undefined) {
|
||||
if (!isBuffer(value)) {
|
||||
throw new Error(`${objectName} must be of type Buffer.`);
|
||||
}
|
||||
value = this.bufferToBase64Url(value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
serializeDateTypes(typeName, value, objectName) {
|
||||
if (value !== null && value !== undefined) {
|
||||
if (typeName.match(/^Date$/ig) !== null) {
|
||||
if (!(value instanceof Date ||
|
||||
(typeof value.valueOf() === "string" && !isNaN(Date.parse(value))))) {
|
||||
throw new Error(`${objectName} must be an instanceof Date or a string in ISO8601 format.`);
|
||||
}
|
||||
value = (value instanceof Date) ? value.toISOString().substring(0, 10) : new Date(value).toISOString().substring(0, 10);
|
||||
}
|
||||
else if (typeName.match(/^DateTime$/ig) !== null) {
|
||||
if (!(value instanceof Date ||
|
||||
(typeof value.valueOf() === "string" && !isNaN(Date.parse(value))))) {
|
||||
throw new Error(`${objectName} must be an instanceof Date or a string in ISO8601 format.`);
|
||||
}
|
||||
value = (value instanceof Date) ? value.toISOString() : new Date(value).toISOString();
|
||||
}
|
||||
else if (typeName.match(/^DateTimeRfc1123$/ig) !== null) {
|
||||
if (!(value instanceof Date ||
|
||||
(typeof value.valueOf() === "string" && !isNaN(Date.parse(value))))) {
|
||||
throw new Error(`${objectName} must be an instanceof Date or a string in RFC-1123 format.`);
|
||||
}
|
||||
value = (value instanceof Date) ? value.toUTCString() : new Date(value).toUTCString();
|
||||
}
|
||||
else if (typeName.match(/^UnixTime$/ig) !== null) {
|
||||
if (!(value instanceof Date ||
|
||||
(typeof value.valueOf() === "string" && !isNaN(Date.parse(value))))) {
|
||||
throw new Error(`${objectName} must be an instanceof Date or a string in RFC-1123/ISO8601 format ` +
|
||||
`for it to be serialized in UnixTime/Epoch format.`);
|
||||
}
|
||||
value = this.dateToUnixTime(value);
|
||||
}
|
||||
else if (typeName.match(/^TimeSpan$/ig) !== null) {
|
||||
if (!moment_1.isDuration(value)) {
|
||||
throw new Error(`${objectName} must be a TimeSpan/Duration.`);
|
||||
}
|
||||
value = value.toISOString();
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
serializeSequenceType(mapper, object, objectName) {
|
||||
if (!Array.isArray(object)) {
|
||||
throw new Error(`${objectName} must be of type Array.`);
|
||||
}
|
||||
if (!mapper.type.element || typeof mapper.type.element !== "object") {
|
||||
throw new Error(`element" metadata for an Array must be defined in the ` +
|
||||
`mapper and it must of type "object" in ${objectName}.`);
|
||||
}
|
||||
const tempArray = [];
|
||||
for (let i = 0; i < object.length; i++) {
|
||||
tempArray[i] = this.serialize(mapper.type.element, object[i], objectName);
|
||||
}
|
||||
return tempArray;
|
||||
}
|
||||
serializeDictionaryType(mapper, object, objectName) {
|
||||
if (typeof object !== "object") {
|
||||
throw new Error(`${objectName} must be of type object.`);
|
||||
}
|
||||
if (!mapper.type.value || typeof mapper.type.value !== "object") {
|
||||
throw new Error(`"value" metadata for a Dictionary must be defined in the ` +
|
||||
`mapper and it must of type "object" in ${objectName}.`);
|
||||
}
|
||||
const tempDictionary = {};
|
||||
for (const key in object) {
|
||||
if (object.hasOwnProperty(key)) {
|
||||
tempDictionary[key] = this.serialize(mapper.type.value, object[key], objectName);
|
||||
}
|
||||
}
|
||||
return tempDictionary;
|
||||
}
|
||||
serializeCompositeType(mapper, object, objectName) {
|
||||
// check for polymorphic discriminator
|
||||
if (mapper.type.polymorphicDiscriminator) {
|
||||
mapper = this.getPolymorphicMapper(mapper, object, objectName, "serialize");
|
||||
}
|
||||
const payload = {};
|
||||
let modelMapper = {
|
||||
required: false,
|
||||
serializedName: "serializedName",
|
||||
type: {
|
||||
name: "Composite",
|
||||
className: "className",
|
||||
modelProperties: {}
|
||||
}
|
||||
};
|
||||
if (object !== null && object !== undefined) {
|
||||
let modelProps = mapper.type.modelProperties;
|
||||
if (!modelProps) {
|
||||
if (!mapper.type.className) {
|
||||
throw new Error(`Class name for model "${objectName}" is not provided in the mapper "${JSON.stringify(mapper, undefined, 2)}".`);
|
||||
}
|
||||
// get the mapper if modelProperties of the CompositeType is not present and
|
||||
// then get the modelProperties from it.
|
||||
modelMapper = this.modelMappers[mapper.type.className];
|
||||
if (!modelMapper) {
|
||||
throw new Error(`mapper() cannot be null or undefined for model "${mapper.type.className}".`);
|
||||
}
|
||||
modelProps = modelMapper.type.modelProperties;
|
||||
if (!modelProps) {
|
||||
throw new Error(`modelProperties cannot be null or undefined in the ` +
|
||||
`mapper "${JSON.stringify(modelMapper)}" of type "${mapper.type.className}" for object "${objectName}".`);
|
||||
}
|
||||
}
|
||||
for (const key in modelProps) {
|
||||
if (modelProps.hasOwnProperty(key)) {
|
||||
const paths = this.splitSerializeName(modelProps[key].serializedName);
|
||||
const propName = paths.pop();
|
||||
let parentObject = payload;
|
||||
paths.forEach((pathName) => {
|
||||
const childObject = parentObject[pathName];
|
||||
if ((childObject === null || childObject === undefined) && (object[key] !== null && object[key] !== undefined)) {
|
||||
parentObject[pathName] = {};
|
||||
}
|
||||
parentObject = parentObject[pathName];
|
||||
});
|
||||
// make sure required properties of the CompositeType are present
|
||||
if (modelProps[key].required && !modelProps[key].isConstant) {
|
||||
if (object[key] === null || object[key] === undefined) {
|
||||
throw new Error(`${key}" cannot be null or undefined in "${objectName}".`);
|
||||
}
|
||||
}
|
||||
// make sure that readOnly properties are not sent on the wire
|
||||
if (modelProps[key].readOnly) {
|
||||
continue;
|
||||
}
|
||||
// serialize the property if it is present in the provided object instance
|
||||
if (((parentObject !== null && parentObject !== undefined) && (modelProps[key].defaultValue !== null && modelProps[key].defaultValue !== undefined)) ||
|
||||
(object[key] !== null && object[key] !== undefined)) {
|
||||
let propertyObjectName = objectName;
|
||||
if (modelProps[key].serializedName !== "")
|
||||
propertyObjectName = objectName + "." + modelProps[key].serializedName;
|
||||
const propertyMapper = modelProps[key];
|
||||
const serializedValue = this.serialize(propertyMapper, object[key], propertyObjectName);
|
||||
if (propName !== null && propName !== undefined)
|
||||
parentObject[propName] = serializedValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
return payload;
|
||||
}
|
||||
return object;
|
||||
}
|
||||
/**
|
||||
* Serialize the given object based on its metadata defined in the mapper
|
||||
*
|
||||
* @param {Mapper} mapper The mapper which defines the metadata of the serializable object
|
||||
*
|
||||
* @param {object|string|Array|number|boolean|Date|stream} object A valid Javascript object to be serialized
|
||||
*
|
||||
* @param {string} objectName Name of the serialized object
|
||||
*
|
||||
* @returns {object|string|Array|number|boolean|Date|stream} A valid serialized Javascript object
|
||||
*/
|
||||
serialize(mapper, object, objectName) {
|
||||
let payload = {};
|
||||
const mapperType = mapper.type.name;
|
||||
if (!objectName)
|
||||
objectName = mapper.serializedName;
|
||||
if (mapperType.match(/^Sequence$/ig) !== null)
|
||||
payload = [];
|
||||
// Throw if required and object is null or undefined
|
||||
if (mapper.required && (object === null || object === undefined) && !mapper.isConstant) {
|
||||
throw new Error(`${objectName} cannot be null or undefined.`);
|
||||
}
|
||||
// Set Defaults
|
||||
if ((mapper.defaultValue !== null && mapper.defaultValue !== undefined) &&
|
||||
(object === null || object === undefined)) {
|
||||
object = mapper.defaultValue;
|
||||
}
|
||||
if (mapper.isConstant)
|
||||
object = mapper.defaultValue;
|
||||
// Validate Constraints if any
|
||||
this.validateConstraints(mapper, object, objectName);
|
||||
if (mapperType.match(/^(Number|String|Boolean|Object|Stream|Uuid)$/ig) !== null) {
|
||||
payload = this.serializeBasicTypes(mapperType, objectName, object);
|
||||
}
|
||||
else if (mapperType.match(/^Enum$/ig) !== null) {
|
||||
const enumMapper = mapper;
|
||||
payload = this.serializeEnumType(objectName, enumMapper.type.allowedValues, object);
|
||||
}
|
||||
else if (mapperType.match(/^(Date|DateTime|TimeSpan|DateTimeRfc1123|UnixTime)$/ig) !== null) {
|
||||
payload = this.serializeDateTypes(mapperType, object, objectName);
|
||||
}
|
||||
else if (mapperType.match(/^ByteArray$/ig) !== null) {
|
||||
payload = this.serializeBufferType(objectName, object);
|
||||
}
|
||||
else if (mapperType.match(/^Base64Url$/ig) !== null) {
|
||||
payload = this.serializeBase64UrlType(objectName, object);
|
||||
}
|
||||
else if (mapperType.match(/^Sequence$/ig) !== null) {
|
||||
payload = this.serializeSequenceType(mapper, object, objectName);
|
||||
}
|
||||
else if (mapperType.match(/^Dictionary$/ig) !== null) {
|
||||
payload = this.serializeDictionaryType(mapper, object, objectName);
|
||||
}
|
||||
else if (mapperType.match(/^Composite$/ig) !== null) {
|
||||
payload = this.serializeCompositeType(mapper, object, objectName);
|
||||
}
|
||||
return payload;
|
||||
}
|
||||
deserializeCompositeType(mapper, responseBody, objectName) {
|
||||
/*jshint validthis: true */
|
||||
// check for polymorphic discriminator
|
||||
if (mapper.type.polymorphicDiscriminator) {
|
||||
mapper = this.getPolymorphicMapper(mapper, responseBody, objectName, "deserialize");
|
||||
}
|
||||
let instance = {};
|
||||
let modelMapper = {
|
||||
required: false,
|
||||
serializedName: "serializedName",
|
||||
type: {
|
||||
name: "Composite"
|
||||
}
|
||||
};
|
||||
if (responseBody !== null && responseBody !== undefined) {
|
||||
let modelProps = mapper.type.modelProperties;
|
||||
if (!modelProps) {
|
||||
if (!mapper.type.className) {
|
||||
throw new Error(`Class name for model "${objectName}" is not provided in the mapper "${JSON.stringify(mapper)}"`);
|
||||
}
|
||||
// get the mapper if modelProperties of the CompositeType is not present and
|
||||
// then get the modelProperties from it.
|
||||
modelMapper = this.modelMappers[mapper.type.className];
|
||||
if (!modelMapper) {
|
||||
throw new Error(`mapper() cannot be null or undefined for model "${mapper.type.className}"`);
|
||||
}
|
||||
modelProps = modelMapper.type.modelProperties;
|
||||
if (!modelProps) {
|
||||
throw new Error(`modelProperties cannot be null or undefined in the ` +
|
||||
`mapper "${JSON.stringify(modelMapper)}" of type "${mapper.type.className}" for responseBody "${objectName}".`);
|
||||
}
|
||||
}
|
||||
for (const key in modelProps) {
|
||||
if (modelProps.hasOwnProperty(key)) {
|
||||
const jpath = ["responseBody"];
|
||||
const paths = this.splitSerializeName(modelProps[key].serializedName);
|
||||
paths.forEach((item) => {
|
||||
jpath.push(`["${item}"]`);
|
||||
});
|
||||
// deserialize the property if it is present in the provided responseBody instance
|
||||
let propertyInstance;
|
||||
try {
|
||||
/*jslint evil: true */
|
||||
propertyInstance = eval(jpath.join(""));
|
||||
}
|
||||
catch (err) {
|
||||
continue;
|
||||
}
|
||||
let propertyObjectName = objectName;
|
||||
if (modelProps[key].serializedName !== "")
|
||||
propertyObjectName = objectName + "." + modelProps[key].serializedName;
|
||||
const propertyMapper = modelProps[key];
|
||||
let serializedValue;
|
||||
// paging
|
||||
if (Array.isArray(responseBody[key]) && modelProps[key].serializedName === "") {
|
||||
propertyInstance = responseBody[key];
|
||||
instance = this.deserialize(propertyMapper, propertyInstance, propertyObjectName);
|
||||
}
|
||||
else if (propertyInstance !== null && propertyInstance !== undefined) {
|
||||
serializedValue = this.deserialize(propertyMapper, propertyInstance, propertyObjectName);
|
||||
instance[key] = serializedValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
return responseBody;
|
||||
}
|
||||
deserializeDictionaryType(mapper, responseBody, objectName) {
|
||||
/*jshint validthis: true */
|
||||
if (!mapper.type.value || typeof mapper.type.value !== "object") {
|
||||
throw new Error(`"value" metadata for a Dictionary must be defined in the ` +
|
||||
`mapper and it must of type "object" in ${objectName}`);
|
||||
}
|
||||
if (responseBody) {
|
||||
const tempDictionary = {};
|
||||
for (const key in responseBody) {
|
||||
if (responseBody.hasOwnProperty(key)) {
|
||||
tempDictionary[key] = this.deserialize(mapper.type.value, responseBody[key], objectName);
|
||||
}
|
||||
}
|
||||
return tempDictionary;
|
||||
}
|
||||
return responseBody;
|
||||
}
|
||||
deserializeSequenceType(mapper, responseBody, objectName) {
|
||||
/*jshint validthis: true */
|
||||
if (!mapper.type.element || typeof mapper.type.element !== "object") {
|
||||
throw new Error(`element" metadata for an Array must be defined in the ` +
|
||||
`mapper and it must of type "object" in ${objectName}`);
|
||||
}
|
||||
if (responseBody) {
|
||||
const tempArray = [];
|
||||
for (let i = 0; i < responseBody.length; i++) {
|
||||
tempArray[i] = this.deserialize(mapper.type.element, responseBody[i], objectName);
|
||||
}
|
||||
return tempArray;
|
||||
}
|
||||
return responseBody;
|
||||
}
|
||||
/**
|
||||
* Deserialize the given object based on its metadata defined in the mapper
|
||||
*
|
||||
* @param {object} mapper The mapper which defines the metadata of the serializable object
|
||||
*
|
||||
* @param {object|string|Array|number|boolean|Date|stream} responseBody A valid Javascript entity to be deserialized
|
||||
*
|
||||
* @param {string} objectName Name of the deserialized object
|
||||
*
|
||||
* @returns {object|string|Array|number|boolean|Date|stream} A valid deserialized Javascript object
|
||||
*/
|
||||
deserialize(mapper, responseBody, objectName) {
|
||||
if (responseBody === null || responseBody === undefined)
|
||||
return responseBody;
|
||||
let payload;
|
||||
const mapperType = mapper.type.name;
|
||||
if (!objectName)
|
||||
objectName = mapper.serializedName;
|
||||
if (mapperType.match(/^Sequence$/ig) !== null)
|
||||
payload = [];
|
||||
if (mapperType.match(/^(Number|String|Boolean|Enum|Object|Stream|Uuid)$/ig) !== null) {
|
||||
payload = responseBody;
|
||||
}
|
||||
else if (mapperType.match(/^(Date|DateTime|DateTimeRfc1123)$/ig) !== null) {
|
||||
payload = new Date(responseBody);
|
||||
}
|
||||
else if (mapperType.match(/^TimeSpan$/ig) !== null) {
|
||||
payload = moment_1.duration(responseBody);
|
||||
}
|
||||
else if (mapperType.match(/^UnixTime$/ig) !== null) {
|
||||
payload = this.unixTimeToDate(responseBody);
|
||||
}
|
||||
else if (mapperType.match(/^ByteArray$/ig) !== null) {
|
||||
payload = Buffer.from(responseBody, "base64");
|
||||
}
|
||||
else if (mapperType.match(/^Base64Url$/ig) !== null) {
|
||||
payload = this.base64UrlToBuffer(responseBody);
|
||||
}
|
||||
else if (mapperType.match(/^Sequence$/ig) !== null) {
|
||||
payload = this.deserializeSequenceType(mapper, responseBody, objectName);
|
||||
}
|
||||
else if (mapperType.match(/^Dictionary$/ig) !== null) {
|
||||
payload = this.deserializeDictionaryType(mapper, responseBody, objectName);
|
||||
}
|
||||
else if (mapperType.match(/^Composite$/ig) !== null) {
|
||||
payload = this.deserializeCompositeType(mapper, responseBody, objectName);
|
||||
}
|
||||
if (mapper.isConstant)
|
||||
payload = mapper.defaultValue;
|
||||
return payload;
|
||||
}
|
||||
getPolymorphicMapper(mapper, object, objectName, mode) {
|
||||
// check for polymorphic discriminator
|
||||
// Until version 1.15.1, "polymorphicDiscriminator" in the mapper was a string. This method was not effective when the
|
||||
// polymorphicDiscriminator property had a dot in it"s name. So we have comeup with a desgin where polymorphicDiscriminator
|
||||
// will be an object that contains the clientName (normalized property name, ex: "odatatype") and
|
||||
// the serializedName (ex: "odata.type") (We do not escape the dots with double backslash in this case as it is not required)
|
||||
// Thus when serializing, the user will give us an object which will contain the normalizedProperty hence we will lookup
|
||||
// the clientName of the polmorphicDiscriminator in the mapper and during deserialization from the responseBody we will
|
||||
// lookup the serializedName of the polmorphicDiscriminator in the mapper. This will help us in selecting the correct mapper
|
||||
// for the model that needs to be serializes or deserialized.
|
||||
// We need this routing for backwards compatibility. This will absorb the breaking change in the mapper and allow new versions
|
||||
// of the runtime to work seamlessly with older version (>= 0.17.0-Nightly20161008) of Autorest generated node.js clients.
|
||||
if (mapper.type.polymorphicDiscriminator) {
|
||||
if (typeof mapper.type.polymorphicDiscriminator.valueOf() === "string") {
|
||||
return this.getPolymorphicMapperStringVersion(mapper, object, objectName);
|
||||
}
|
||||
else if (mapper.type.polymorphicDiscriminator instanceof Object) {
|
||||
return this.getPolymorphicMapperObjectVersion(mapper, object, objectName, mode);
|
||||
}
|
||||
else {
|
||||
throw new Error(`The polymorphicDiscriminator for "${objectName}" is neither a string nor an object.`);
|
||||
}
|
||||
}
|
||||
return mapper;
|
||||
}
|
||||
// processes new version of the polymorphicDiscriminator in the mapper.
|
||||
getPolymorphicMapperObjectVersion(mapper, object, objectName, mode) {
|
||||
// check for polymorphic discriminator
|
||||
let polymorphicPropertyName = "";
|
||||
if (mode === "serialize") {
|
||||
polymorphicPropertyName = "clientName";
|
||||
}
|
||||
else if (mode === "deserialize") {
|
||||
polymorphicPropertyName = "serializedName";
|
||||
}
|
||||
else {
|
||||
throw new Error(`The given mode "${mode}" for getting the polymorphic mapper for "${objectName}" is inavlid.`);
|
||||
}
|
||||
const discriminatorAsObject = mapper.type.polymorphicDiscriminator;
|
||||
if (discriminatorAsObject &&
|
||||
discriminatorAsObject[polymorphicPropertyName] !== null &&
|
||||
discriminatorAsObject[polymorphicPropertyName] !== undefined) {
|
||||
if (object === null || object === undefined) {
|
||||
throw new Error(`${objectName}" cannot be null or undefined. ` +
|
||||
`"${discriminatorAsObject[polymorphicPropertyName]}" is the ` +
|
||||
`polmorphicDiscriminator and is a required property.`);
|
||||
}
|
||||
if (object[discriminatorAsObject[polymorphicPropertyName]] === null ||
|
||||
object[discriminatorAsObject[polymorphicPropertyName]] === undefined) {
|
||||
throw new Error(`No discriminator field "${discriminatorAsObject[polymorphicPropertyName]}" was found in "${objectName}".`);
|
||||
}
|
||||
let indexDiscriminator = undefined;
|
||||
if (object[discriminatorAsObject[polymorphicPropertyName]] === mapper.type.uberParent) {
|
||||
indexDiscriminator = object[discriminatorAsObject[polymorphicPropertyName]];
|
||||
}
|
||||
else {
|
||||
indexDiscriminator = mapper.type.uberParent + "." + object[discriminatorAsObject[polymorphicPropertyName]];
|
||||
}
|
||||
if (!this.modelMappers.discriminators[indexDiscriminator]) {
|
||||
throw new Error(`${discriminatorAsObject[polymorphicPropertyName]}": ` +
|
||||
`"${object[discriminatorAsObject[polymorphicPropertyName]]}" in "${objectName}" is not a valid ` +
|
||||
`discriminator as a corresponding model class for the disciminator "${indexDiscriminator}" ` +
|
||||
`was not found in this.modelMappers.discriminators object.`);
|
||||
}
|
||||
mapper = this.modelMappers.discriminators[indexDiscriminator];
|
||||
}
|
||||
return mapper;
|
||||
}
|
||||
// processes old version of the polymorphicDiscriminator in the mapper.
|
||||
getPolymorphicMapperStringVersion(mapper, object, objectName) {
|
||||
// check for polymorphic discriminator
|
||||
const discriminatorAsString = mapper.type.polymorphicDiscriminator;
|
||||
if (discriminatorAsString !== null && discriminatorAsString !== undefined) {
|
||||
if (object === null || object === undefined) {
|
||||
throw new Error(`${objectName}" cannot be null or undefined. "${discriminatorAsString}" is the ` +
|
||||
`polmorphicDiscriminator and is a required property.`);
|
||||
}
|
||||
if (object[discriminatorAsString] === null || object[discriminatorAsString] === undefined) {
|
||||
throw new Error(`No discriminator field "${discriminatorAsString}" was found in "${objectName}".`);
|
||||
}
|
||||
let indexDiscriminator = undefined;
|
||||
if (object[discriminatorAsString] === mapper.type.uberParent) {
|
||||
indexDiscriminator = object[discriminatorAsString];
|
||||
}
|
||||
else {
|
||||
indexDiscriminator = mapper.type.uberParent + "." + object[discriminatorAsString];
|
||||
}
|
||||
if (!this.modelMappers.discriminators[indexDiscriminator]) {
|
||||
throw new Error(`${discriminatorAsString}": ` +
|
||||
`"${object[discriminatorAsString]}" in "${objectName}" is not a valid ` +
|
||||
`discriminator as a corresponding model class for the disciminator "${indexDiscriminator}" ` +
|
||||
`was not found in this.models.discriminators object.`);
|
||||
}
|
||||
mapper = this.modelMappers.discriminators[indexDiscriminator];
|
||||
}
|
||||
return mapper;
|
||||
}
|
||||
}
|
||||
exports.Serializer = Serializer;
|
||||
function serializeObject(toSerialize) {
|
||||
if (toSerialize === null || toSerialize === undefined)
|
||||
return undefined;
|
||||
if (isBuffer(toSerialize)) {
|
||||
toSerialize = toSerialize.toString("base64");
|
||||
return toSerialize;
|
||||
}
|
||||
else if (toSerialize instanceof Date) {
|
||||
return toSerialize.toISOString();
|
||||
}
|
||||
else if (Array.isArray(toSerialize)) {
|
||||
const array = [];
|
||||
for (let i = 0; i < toSerialize.length; i++) {
|
||||
array.push(serializeObject(toSerialize[i]));
|
||||
}
|
||||
return array;
|
||||
}
|
||||
else if (typeof toSerialize === "object") {
|
||||
const dictionary = {};
|
||||
for (const property in toSerialize) {
|
||||
dictionary[property] = serializeObject(toSerialize[property]);
|
||||
}
|
||||
return dictionary;
|
||||
}
|
||||
return toSerialize;
|
||||
}
|
||||
exports.serializeObject = serializeObject;
|
||||
exports.MapperType = utils.strEnum([
|
||||
"Base64Url",
|
||||
"Boolean",
|
||||
"ByteArray",
|
||||
"Composite",
|
||||
"Date",
|
||||
"DateTime",
|
||||
"DateTimeRfc1123",
|
||||
"Dictionary",
|
||||
"Enum",
|
||||
"Number",
|
||||
"Object",
|
||||
"Sequence",
|
||||
"String",
|
||||
"Stream",
|
||||
"TimeSpan",
|
||||
"UnixTime"
|
||||
]);
|
||||
//# sourceMappingURL=serializer.js.map
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -0,0 +1,110 @@
|
|||
"use strict";
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const requestPipeline_1 = require("./requestPipeline");
|
||||
const exponentialRetryPolicyFilter_1 = require("./filters/exponentialRetryPolicyFilter");
|
||||
const systemErrorRetryPolicyFilter_1 = require("./filters/systemErrorRetryPolicyFilter");
|
||||
const redirectFilter_1 = require("./filters/redirectFilter");
|
||||
const signingFilter_1 = require("./filters/signingFilter");
|
||||
const rpRegistrationFilter_1 = require("./filters/rpRegistrationFilter");
|
||||
const msRestUserAgentFilter_1 = require("./filters/msRestUserAgentFilter");
|
||||
const webResource_1 = require("./webResource");
|
||||
const constants_1 = require("./util/constants");
|
||||
/**
|
||||
* @class
|
||||
* Initializes a new instance of the ServiceClient.
|
||||
*/
|
||||
class ServiceClient {
|
||||
/**
|
||||
* The ServiceClient constructor
|
||||
* @constructor
|
||||
* @param {ServiceClientCredentials }[credentials] - BasicAuthenticationCredentials or
|
||||
* TokenCredentials object used for authentication.
|
||||
* @param { ServiceClientOptions } [options] The service client options that govern the behavior of the client.
|
||||
*/
|
||||
constructor(credentials, options) {
|
||||
if (!options) {
|
||||
options = {};
|
||||
}
|
||||
if (!options.requestOptions) {
|
||||
options.requestOptions = {};
|
||||
}
|
||||
if (!options.filters) {
|
||||
options.filters = [];
|
||||
}
|
||||
this.userAgentInfo = { value: [] };
|
||||
if (credentials && !credentials.signRequest) {
|
||||
throw new Error("credentials argument needs to implement signRequest method");
|
||||
}
|
||||
try {
|
||||
const moduleName = "ms-rest-js";
|
||||
const moduleVersion = constants_1.Constants.msRestVersion;
|
||||
this.addUserAgentInfo(`${moduleName}/${moduleVersion}`);
|
||||
}
|
||||
catch (err) {
|
||||
// do nothing
|
||||
}
|
||||
if (credentials) {
|
||||
options.filters.push(new signingFilter_1.SigningFilter(credentials));
|
||||
}
|
||||
options.filters.push(new msRestUserAgentFilter_1.MsRestUserAgentFilter(this.userAgentInfo.value));
|
||||
options.filters.push(new redirectFilter_1.RedirectFilter());
|
||||
options.filters.push(new rpRegistrationFilter_1.RPRegistrationFilter(options.rpRegistrationRetryTimeout));
|
||||
if (!options.noRetryPolicy) {
|
||||
options.filters.push(new exponentialRetryPolicyFilter_1.ExponentialRetryPolicyFilter());
|
||||
options.filters.push(new systemErrorRetryPolicyFilter_1.SystemErrorRetryPolicyFilter());
|
||||
}
|
||||
this.pipeline = new requestPipeline_1.RequestPipeline(options.filters, options.requestOptions).create();
|
||||
}
|
||||
/**
|
||||
* Adds custom information to user agent header
|
||||
* @param {any} additionalUserAgentInfo - information to be added to user agent header, as string.
|
||||
*/
|
||||
addUserAgentInfo(additionalUserAgentInfo) {
|
||||
if (this.userAgentInfo.value.indexOf(additionalUserAgentInfo) === -1) {
|
||||
this.userAgentInfo.value.push(additionalUserAgentInfo);
|
||||
}
|
||||
return;
|
||||
}
|
||||
sendRequest(options) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
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;
|
||||
try {
|
||||
if (options instanceof webResource_1.WebResource) {
|
||||
options.validateRequestProperties();
|
||||
httpRequest = options;
|
||||
}
|
||||
else {
|
||||
httpRequest = new webResource_1.WebResource();
|
||||
httpRequest = httpRequest.prepare(options);
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
return Promise.reject(error);
|
||||
}
|
||||
// send request
|
||||
let operationResponse;
|
||||
try {
|
||||
operationResponse = yield this.pipeline(httpRequest);
|
||||
}
|
||||
catch (err) {
|
||||
return Promise.reject(err);
|
||||
}
|
||||
return Promise.resolve(operationResponse);
|
||||
});
|
||||
}
|
||||
}
|
||||
exports.ServiceClient = ServiceClient;
|
||||
//# sourceMappingURL=serviceClient.js.map
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"serviceClient.js","sourceRoot":"","sources":["../../lib/serviceClient.ts"],"names":[],"mappings":"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"}
|
|
@ -0,0 +1,78 @@
|
|||
"use strict";
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.Constants = {
|
||||
/**
|
||||
* The ms-rest version
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
msRestVersion: "0.1.0",
|
||||
/**
|
||||
* 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",
|
||||
HttpConstants: {
|
||||
/**
|
||||
* Http Verbs
|
||||
*
|
||||
* @const
|
||||
* @enum {string}
|
||||
*/
|
||||
HttpVerbs: {
|
||||
PUT: "PUT",
|
||||
GET: "GET",
|
||||
DELETE: "DELETE",
|
||||
POST: "POST",
|
||||
MERGE: "MERGE",
|
||||
HEAD: "HEAD",
|
||||
PATCH: "PATCH"
|
||||
},
|
||||
},
|
||||
/**
|
||||
* Defines constants for use with HTTP headers.
|
||||
*/
|
||||
HeaderConstants: {
|
||||
/**
|
||||
* The Authorization header.
|
||||
*
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
AUTHORIZATION: "authorization",
|
||||
AUTHORIZATION_SCHEME: "Bearer",
|
||||
/**
|
||||
* The UserAgent header.
|
||||
*
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
USER_AGENT: "User-Agent"
|
||||
}
|
||||
};
|
||||
//# sourceMappingURL=constants.js.map
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../lib/util/constants.ts"],"names":[],"mappings":";AAAA,4DAA4D;AAC5D,+FAA+F;;AAElF,QAAA,SAAS,GAAG;IAEvB;;;;OAIG;IACH,aAAa,EAAE,OAAO;IAEtB;;;;;OAKG;IACH,IAAI,EAAE,OAAO;IAEb;;;;;OAKG;IACH,KAAK,EAAE,QAAQ;IAEf;;;;;OAKG;IACH,UAAU,EAAE,YAAY;IAExB;;;;;OAKG;IACH,WAAW,EAAE,aAAa;IAE1B,aAAa,EAAE;QACb;;;;;WAKG;QACH,SAAS,EAAE;YACT,GAAG,EAAE,KAAK;YACV,GAAG,EAAE,KAAK;YACV,MAAM,EAAE,QAAQ;YAChB,IAAI,EAAE,MAAM;YACZ,KAAK,EAAE,OAAO;YACd,IAAI,EAAE,MAAM;YACZ,KAAK,EAAE,OAAO;SACf;KACF;IAED;;OAEG;IACH,eAAe,EAAE;QACf;;;;;WAKG;QACH,aAAa,EAAE,eAAe;QAE9B,oBAAoB,EAAE,QAAQ;QAE9B;;;;;WAKG;QACH,UAAU,EAAE,YAAY;KACzB;CACF,CAAC"}
|
|
@ -0,0 +1,329 @@
|
|||
"use strict";
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const uuid = require("uuid");
|
||||
const FormData = require("form-data");
|
||||
const webResource_1 = require("../webResource");
|
||||
const constants_1 = require("./constants");
|
||||
const restError_1 = require("../restError");
|
||||
const httpOperationResponse_1 = require("../httpOperationResponse");
|
||||
/**
|
||||
* Provides the fetch() method based on the environment.
|
||||
* @returns {fetch} fetch - The fetch() method available in the environment to make requests
|
||||
*/
|
||||
function getFetch() {
|
||||
// using window.Fetch in Edge gives a TypeMismatchError
|
||||
// (https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/8546263/).
|
||||
// Hence we will be using the fetch-ponyfill for Edge.
|
||||
if (typeof window !== "undefined" && window.fetch && window.navigator &&
|
||||
window.navigator.userAgent && window.navigator.userAgent.indexOf("Edge/") === -1) {
|
||||
return window.fetch.bind(window);
|
||||
}
|
||||
return require("fetch-ponyfill")({ useCookie: true }).fetch;
|
||||
}
|
||||
exports.getFetch = getFetch;
|
||||
/**
|
||||
* A constant that provides the fetch() method based on the environment.
|
||||
*/
|
||||
exports.myFetch = getFetch();
|
||||
/**
|
||||
* Checks if a parsed URL is HTTPS
|
||||
*
|
||||
* @param {object} urlToCheck The url to check
|
||||
* @return {boolean} True if the URL is HTTPS; false otherwise.
|
||||
*/
|
||||
function urlIsHTTPS(urlToCheck) {
|
||||
return urlToCheck.protocol.toLowerCase() === constants_1.Constants.HTTPS;
|
||||
}
|
||||
exports.urlIsHTTPS = urlIsHTTPS;
|
||||
/**
|
||||
* Checks if a value is null or undefined.
|
||||
*
|
||||
* @param {object} value The value to check for null or undefined.
|
||||
* @return {boolean} True if the value is null or undefined, false otherwise.
|
||||
*/
|
||||
// TODO: Audit the usages of this and remove them.
|
||||
// Read: https://medium.com/@basarat/null-vs-undefined-in-typescript-land-dc0c7a5f240a
|
||||
// https://github.com/Microsoft/TypeScript/issues/7426
|
||||
function objectIsNull(value) {
|
||||
return value === null || value === undefined;
|
||||
}
|
||||
exports.objectIsNull = objectIsNull;
|
||||
/**
|
||||
* Encodes an URI.
|
||||
*
|
||||
* @param {string} uri The URI to be encoded.
|
||||
* @return {string} The encoded URI.
|
||||
*/
|
||||
function encodeUri(uri) {
|
||||
return encodeURIComponent(uri)
|
||||
.replace(/!/g, "%21")
|
||||
.replace(/"/g, "%27")
|
||||
.replace(/\(/g, "%28")
|
||||
.replace(/\)/g, "%29")
|
||||
.replace(/\*/g, "%2A");
|
||||
}
|
||||
exports.encodeUri = encodeUri;
|
||||
/**
|
||||
* Returns a stripped version of the Http Response which only contains body,
|
||||
* headers and the status.
|
||||
*
|
||||
* @param {nodeFetch.Response} response - The Http Response
|
||||
*
|
||||
* @return {object} strippedResponse - The stripped version of Http Response.
|
||||
*/
|
||||
function stripResponse(response) {
|
||||
const strippedResponse = {};
|
||||
strippedResponse.body = response.body;
|
||||
strippedResponse.headers = response.headers;
|
||||
strippedResponse.status = response.status;
|
||||
return strippedResponse;
|
||||
}
|
||||
exports.stripResponse = stripResponse;
|
||||
/**
|
||||
* Returns a stripped version of the Http Request that does not contain the
|
||||
* Authorization header.
|
||||
*
|
||||
* @param {object} request - The Http Request object
|
||||
*
|
||||
* @return {object} strippedRequest - The stripped version of Http Request.
|
||||
*/
|
||||
function stripRequest(request) {
|
||||
let strippedRequest = new webResource_1.WebResource();
|
||||
try {
|
||||
strippedRequest = JSON.parse(JSON.stringify(request));
|
||||
if (strippedRequest.headers && strippedRequest.headers.Authorization) {
|
||||
delete strippedRequest.headers.Authorization;
|
||||
}
|
||||
else if (strippedRequest.headers && strippedRequest.headers.authorization) {
|
||||
delete strippedRequest.headers.authorization;
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
const errMsg = err.message;
|
||||
err.message = `Error - "${errMsg}" occured while creating a stripped version of the request object - "${request}".`;
|
||||
return err;
|
||||
}
|
||||
return strippedRequest;
|
||||
}
|
||||
exports.stripRequest = stripRequest;
|
||||
/**
|
||||
* Validates the given uuid as a string
|
||||
*
|
||||
* @param {string} uuid - The uuid as a string that needs to be validated
|
||||
*
|
||||
* @return {boolean} result - True if the uuid is valid; false otherwise.
|
||||
*/
|
||||
function isValidUuid(uuid) {
|
||||
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);
|
||||
}
|
||||
exports.isValidUuid = isValidUuid;
|
||||
/**
|
||||
* 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 {array} result - An array of values of the given object.
|
||||
*/
|
||||
function objectValues(obj) {
|
||||
const result = [];
|
||||
if (obj && obj instanceof Object) {
|
||||
for (const key in obj) {
|
||||
if (obj.hasOwnProperty(key)) {
|
||||
result.push(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;
|
||||
}
|
||||
exports.objectValues = objectValues;
|
||||
/**
|
||||
* Generated UUID
|
||||
*
|
||||
* @return {string} RFC4122 v4 UUID.
|
||||
*/
|
||||
function generateUuid() {
|
||||
return uuid.v4();
|
||||
}
|
||||
exports.generateUuid = generateUuid;
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
function executePromisesSequentially(promiseFactories, kickstart) {
|
||||
let result = Promise.resolve(kickstart);
|
||||
promiseFactories.forEach((promiseFactory) => {
|
||||
result = result.then(promiseFactory);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
exports.executePromisesSequentially = executePromisesSequentially;
|
||||
/*
|
||||
* 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} target - Returns the merged target object.
|
||||
*/
|
||||
function mergeObjects(source, target) {
|
||||
Object.keys(source).forEach((key) => {
|
||||
target[key] = source[key];
|
||||
});
|
||||
return target;
|
||||
}
|
||||
exports.mergeObjects = mergeObjects;
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
function delay(t, value) {
|
||||
return new Promise((resolve) => setTimeout(() => resolve(value), t));
|
||||
}
|
||||
exports.delay = delay;
|
||||
/**
|
||||
* Utility function to create a K:V from a list of strings
|
||||
*/
|
||||
function strEnum(o) {
|
||||
return o.reduce((res, key) => {
|
||||
res[key] = key;
|
||||
return res;
|
||||
}, Object.create(null));
|
||||
}
|
||||
exports.strEnum = strEnum;
|
||||
/**
|
||||
* Converts a Promise to a callback.
|
||||
* @param {Promise<any>} promise - The Promise to be converted to a callback
|
||||
* @returns {Function} fn - A function that takes the callback (cb: Function): void
|
||||
*/
|
||||
function promiseToCallback(promise) {
|
||||
if (typeof promise.then !== "function") {
|
||||
throw new Error("The provided input is not a Promise.");
|
||||
}
|
||||
return (cb) => {
|
||||
promise.then((data) => {
|
||||
process.nextTick(cb, undefined, data);
|
||||
}, (err) => {
|
||||
process.nextTick(cb, err);
|
||||
});
|
||||
};
|
||||
}
|
||||
exports.promiseToCallback = promiseToCallback;
|
||||
/**
|
||||
* Converts a Promise to a service callback.
|
||||
* @param {Promise<HttpOperationResponse>} promise - The Promise of HttpOperationResponse to be converted to a service callback
|
||||
* @returns {Function} fn - A function that takes the service callback (cb: ServiceCallback<T>): void
|
||||
*/
|
||||
function promiseToServiceCallback(promise) {
|
||||
if (typeof promise.then !== "function") {
|
||||
throw new Error("The provided input is not a Promise.");
|
||||
}
|
||||
return (cb) => {
|
||||
promise.then((data) => {
|
||||
process.nextTick(cb, undefined, data.bodyAsJson, data.request, data.response);
|
||||
}, (err) => {
|
||||
process.nextTick(cb, err);
|
||||
});
|
||||
};
|
||||
}
|
||||
exports.promiseToServiceCallback = promiseToServiceCallback;
|
||||
/**
|
||||
* Sends the request and returns the received response.
|
||||
* @param {WebResource} options - The request to be sent.
|
||||
* @returns {Promise<HttpOperationResponse} operationResponse - The response object.
|
||||
*/
|
||||
function dispatchRequest(options) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
if (!options) {
|
||||
return Promise.reject(new Error("options (WebResource) cannot be null or undefined and must be of type object."));
|
||||
}
|
||||
if (options.formData) {
|
||||
const formData = options.formData;
|
||||
const requestForm = new FormData();
|
||||
const appendFormValue = (key, value) => {
|
||||
if (value && value.hasOwnProperty("value") && value.hasOwnProperty("options")) {
|
||||
requestForm.append(key, value.value, value.options);
|
||||
}
|
||||
else {
|
||||
requestForm.append(key, value);
|
||||
}
|
||||
};
|
||||
for (const formKey in formData) {
|
||||
if (formData.hasOwnProperty(formKey)) {
|
||||
const formValue = formData[formKey];
|
||||
if (formValue instanceof Array) {
|
||||
for (let j = 0; j < formValue.length; j++) {
|
||||
appendFormValue(formKey, formValue[j]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
appendFormValue(formKey, formValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
options.body = requestForm;
|
||||
options.formData = undefined;
|
||||
if (options.headers && options.headers["Content-Type"] &&
|
||||
options.headers["Content-Type"].indexOf("multipart/form-data") > -1 && typeof requestForm.getBoundary === "function") {
|
||||
options.headers["Content-Type"] = `multipart/form-data; boundary=${requestForm.getBoundary()}`;
|
||||
}
|
||||
}
|
||||
let res;
|
||||
try {
|
||||
res = yield exports.myFetch(options.url, options);
|
||||
}
|
||||
catch (err) {
|
||||
return Promise.reject(err);
|
||||
}
|
||||
const operationResponse = new httpOperationResponse_1.HttpOperationResponse(options, res, res.body);
|
||||
if (!options.rawResponse) {
|
||||
try {
|
||||
operationResponse.bodyAsText = yield res.text();
|
||||
}
|
||||
catch (err) {
|
||||
const msg = `Error "${err}" occured while converting the raw response body into string.`;
|
||||
const errCode = err.code || "RAWTEXT_CONVERSION_ERROR";
|
||||
const e = new restError_1.RestError(msg, errCode, res.status, options, res, res.body);
|
||||
return Promise.reject(e);
|
||||
}
|
||||
try {
|
||||
if (operationResponse.bodyAsText) {
|
||||
operationResponse.bodyAsJson = JSON.parse(operationResponse.bodyAsText);
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
const msg = `Error "${err}" occured while executing JSON.parse on the response body - ${operationResponse.bodyAsText}.`;
|
||||
const errCode = err.code || "JSON_PARSE_ERROR";
|
||||
const e = new restError_1.RestError(msg, errCode, res.status, options, res, operationResponse.bodyAsText);
|
||||
return Promise.reject(e);
|
||||
}
|
||||
}
|
||||
return Promise.resolve(operationResponse);
|
||||
});
|
||||
}
|
||||
exports.dispatchRequest = dispatchRequest;
|
||||
//# sourceMappingURL=utils.js.map
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -0,0 +1,206 @@
|
|||
"use strict";
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const utils_1 = require("./util/utils");
|
||||
const serializer_1 = require("./serializer");
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
class WebResource {
|
||||
constructor(url, method, body, query, headers = {}, rawResponse = false) {
|
||||
this.headers = {};
|
||||
this.rawResponse = rawResponse;
|
||||
this.url = url || "";
|
||||
this.method = method || "GET";
|
||||
this.headers = headers || {};
|
||||
this.body = body;
|
||||
this.query = query;
|
||||
this.formData = undefined;
|
||||
}
|
||||
/**
|
||||
* 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() {
|
||||
if (!this.method || !this.url || !this.headers["Content-Type"] || !this.headers["accept-language"]) {
|
||||
throw new Error("method, url, headers[\"Content-Type\"], headers[\"accept-language\"] are " +
|
||||
"required properties before making a request. Either provide them or use WebResource.prepare() method.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* Prepares the request.
|
||||
* @param {RequestPrepareOptions} options - Options to provide for preparing the request.
|
||||
* @returns {object} WebResource Returns the prepared WebResource (HTTP Request) object that needs to be given to the request pipeline.
|
||||
*/
|
||||
prepare(options) {
|
||||
if (options === null || options === undefined || typeof options !== "object") {
|
||||
throw new Error("options cannot be null or undefined and must be of type object");
|
||||
}
|
||||
if (options.method === null || options.method === undefined || typeof options.method.valueOf() !== "string") {
|
||||
throw new Error("options.method cannot be null or undefined and it must be of type string.");
|
||||
}
|
||||
if (options.url && options.pathTemplate) {
|
||||
throw new Error("options.url and options.pathTemplate are mutually exclusive. Please provide either of them.");
|
||||
}
|
||||
if ((options.pathTemplate === null || options.pathTemplate === undefined || typeof options.pathTemplate.valueOf() !== "string") && (options.url === null || options.url === undefined || typeof options.url.valueOf() !== "string")) {
|
||||
throw new Error("Please provide either options.pathTemplate or options.url. Currently none of them were provided.");
|
||||
}
|
||||
// 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();
|
||||
// construct the url if path template is provided
|
||||
if (options.pathTemplate) {
|
||||
if (typeof options.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("/") ? "" : "/") + (options.pathTemplate.startsWith("/") ? options.pathTemplate.slice(1) : options.pathTemplate);
|
||||
const segments = url.match(/({\w*\s*\w*})/ig);
|
||||
if (segments && segments.length) {
|
||||
if (options.pathParameters === null || options.pathParameters === undefined || typeof options.pathParameters !== "object") {
|
||||
throw new Error(`pathTemplate: ${options.pathTemplate} has been provided. Hence, options.pathParameters ` +
|
||||
`cannot be null or undefined and must be of type "object".`);
|
||||
}
|
||||
segments.forEach(function (item) {
|
||||
const pathParamName = item.slice(1, -1);
|
||||
const pathParam = options.pathParameters[pathParamName];
|
||||
if (pathParam === null || pathParam === undefined || !(typeof pathParam === "string" || typeof pathParam === "object")) {
|
||||
throw new Error(`pathTemplate: ${options.pathTemplate} contains the path parameter ${pathParamName}` +
|
||||
` however, it is not present in ${options.pathParameters} - ${JSON.stringify(options.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) {
|
||||
if (typeof options.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 = [];
|
||||
const queryParameters = options.queryParameters;
|
||||
// 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 = 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 in headers) {
|
||||
if (headers.hasOwnProperty(headerName)) {
|
||||
this.headers[headerName] = headers[headerName];
|
||||
}
|
||||
}
|
||||
}
|
||||
// ensure accept-language is set correctly
|
||||
if (!this.headers["accept-language"]) {
|
||||
this.headers["accept-language"] = "en-US";
|
||||
}
|
||||
// ensure the request-id is set correctly
|
||||
if (!this.headers["x-ms-client-request-id"] && !options.disableClientRequestId) {
|
||||
this.headers["x-ms-client-request-id"] = utils_1.generateUuid();
|
||||
}
|
||||
// default
|
||||
if (!this.headers["Content-Type"]) {
|
||||
this.headers["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 = undefined;
|
||||
if (options.body !== null && 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) {
|
||||
this.body = options.body;
|
||||
if (!this.headers["Transfer-Encoding"]) {
|
||||
this.headers["Transfer-Encoding"] = "chunked";
|
||||
}
|
||||
if (this.headers["Content-Type"] !== "application/octet-stream") {
|
||||
this.headers["Content-Type"] = "application/octet-stream";
|
||||
}
|
||||
}
|
||||
else {
|
||||
let serializedBody = undefined;
|
||||
if (options.serializationMapper) {
|
||||
serializedBody = new serializer_1.Serializer(options.mappers).serialize(options.serializationMapper, options.body, "requestBody");
|
||||
}
|
||||
if (options.disableJsonStringifyOnBody) {
|
||||
this.body = serializedBody || options.body;
|
||||
}
|
||||
else {
|
||||
this.body = serializedBody ? JSON.stringify(serializedBody) : JSON.stringify(options.body);
|
||||
}
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
||||
exports.WebResource = WebResource;
|
||||
//# sourceMappingURL=webResource.js.map
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -0,0 +1,96 @@
|
|||
"use strict";
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const msRest = require("../lib/msRest");
|
||||
const should = require("should");
|
||||
const TokenCredentials = msRest.TokenCredentials;
|
||||
const BasicAuthenticationCredentials = msRest.BasicAuthenticationCredentials;
|
||||
const dummyToken = "A-dummy-access-token";
|
||||
const fakeScheme = "fake-auth-scheme";
|
||||
const dummyuserName = "dummy@mummy.com";
|
||||
const dummyPassword = "IL0veDummies";
|
||||
describe("Token credentials", () => {
|
||||
describe("usage", () => {
|
||||
it("should set auth header with bearer scheme in request", (done) => {
|
||||
const creds = new TokenCredentials(dummyToken);
|
||||
const request = new msRest.WebResource();
|
||||
request.headers = {};
|
||||
creds.signRequest(request).then((signedRequest) => {
|
||||
should.exist(signedRequest.headers["authorization"]);
|
||||
signedRequest.headers["authorization"].should.match(new RegExp("^Bearer\\s+" + dummyToken + "$"));
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("should set auth header with custom scheme in request", (done) => {
|
||||
const creds = new TokenCredentials(dummyToken, fakeScheme);
|
||||
const request = new msRest.WebResource();
|
||||
request.headers = {};
|
||||
creds.signRequest(request).then((signedRequest) => {
|
||||
should.exist(signedRequest.headers["authorization"]);
|
||||
signedRequest.headers["authorization"].should.match(new RegExp("^" + fakeScheme + "\\s+" + dummyToken + "$"));
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
describe("construction", () => {
|
||||
it("should succeed with token", () => {
|
||||
(() => {
|
||||
new TokenCredentials(dummyToken);
|
||||
}).should.not.throw();
|
||||
});
|
||||
// it("should fail without credentials", () => {
|
||||
// (() => {
|
||||
// new TokenCredentials();
|
||||
// }).should.throw();
|
||||
// });
|
||||
// it("should fail without token", () => {
|
||||
// (() => {
|
||||
// new TokenCredentials(null, fakeScheme);
|
||||
// }).should.throw();
|
||||
// });
|
||||
});
|
||||
});
|
||||
describe("Basic Authentication credentials", () => {
|
||||
const encodedCredentials = Buffer.from(dummyuserName + ":" + dummyPassword).toString("base64");
|
||||
describe("usage", () => {
|
||||
it("should base64 encode the username and password and set auth header with baisc scheme in request", (done) => {
|
||||
const creds = new BasicAuthenticationCredentials(dummyuserName, dummyPassword);
|
||||
const request = new msRest.WebResource();
|
||||
request.headers = {};
|
||||
creds.signRequest(request).then((signedRequest) => {
|
||||
signedRequest.headers.should.have.property("authorization");
|
||||
signedRequest.headers["authorization"].should.match(new RegExp("^Basic\\s+" + encodedCredentials + "$"));
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("should base64 encode the username and password and set auth header with custom scheme in request", (done) => {
|
||||
const creds = new BasicAuthenticationCredentials(dummyuserName, dummyPassword, fakeScheme);
|
||||
const request = new msRest.WebResource();
|
||||
request.headers = {};
|
||||
creds.signRequest(request).then((signedRequest) => {
|
||||
signedRequest.headers.should.have.property("authorization");
|
||||
signedRequest.headers["authorization"].should.match(new RegExp("^" + fakeScheme + "\\s+" + encodedCredentials + "$"));
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
describe("construction", () => {
|
||||
it("should succeed with userName and password", () => {
|
||||
(() => {
|
||||
new BasicAuthenticationCredentials(dummyuserName, dummyPassword);
|
||||
}).should.not.throw();
|
||||
});
|
||||
// it("should fail without credentials", () => {
|
||||
// (() => {
|
||||
// new BasicAuthenticationCredentials(null, null);
|
||||
// }).should.throw();
|
||||
// });
|
||||
// it("should fail without userName and password", () => {
|
||||
// (() => {
|
||||
// new BasicAuthenticationCredentials(null, null, fakeScheme);
|
||||
// }).should.throw();
|
||||
// });
|
||||
});
|
||||
});
|
||||
//# sourceMappingURL=credentialTests.js.map
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"credentialTests.js","sourceRoot":"","sources":["../../test/credentialTests.ts"],"names":[],"mappings":"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"}
|
|
@ -0,0 +1,590 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
/*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for
|
||||
* license information.
|
||||
*/
|
||||
let internalMappers = {};
|
||||
internalMappers.Cat = {
|
||||
required: false,
|
||||
serializedName: "cat",
|
||||
type: {
|
||||
name: "Composite",
|
||||
className: "Cat",
|
||||
modelProperties: {
|
||||
id: {
|
||||
required: false,
|
||||
serializedName: "id",
|
||||
type: {
|
||||
name: "Number"
|
||||
}
|
||||
},
|
||||
name: {
|
||||
required: false,
|
||||
serializedName: "name",
|
||||
type: {
|
||||
name: "String"
|
||||
}
|
||||
},
|
||||
pettype: {
|
||||
required: true,
|
||||
serializedName: "pet\\.type",
|
||||
type: {
|
||||
name: "String"
|
||||
}
|
||||
},
|
||||
color: {
|
||||
required: false,
|
||||
serializedName: "color",
|
||||
type: {
|
||||
name: "String"
|
||||
}
|
||||
},
|
||||
hates: {
|
||||
required: false,
|
||||
serializedName: "hates",
|
||||
type: {
|
||||
name: "Sequence",
|
||||
element: {
|
||||
required: false,
|
||||
serializedName: "DogElementType",
|
||||
type: {
|
||||
name: "Composite",
|
||||
className: "Dog"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
internalMappers.Dog = {
|
||||
required: false,
|
||||
serializedName: "dog",
|
||||
type: {
|
||||
name: "Composite",
|
||||
className: "Dog",
|
||||
modelProperties: {
|
||||
id: {
|
||||
required: false,
|
||||
serializedName: "id",
|
||||
type: {
|
||||
name: "Number"
|
||||
}
|
||||
},
|
||||
name: {
|
||||
required: false,
|
||||
serializedName: "name",
|
||||
type: {
|
||||
name: "String"
|
||||
}
|
||||
},
|
||||
pettype: {
|
||||
required: true,
|
||||
serializedName: "pet\\.type",
|
||||
type: {
|
||||
name: "String"
|
||||
}
|
||||
},
|
||||
food: {
|
||||
required: false,
|
||||
serializedName: "food",
|
||||
type: {
|
||||
name: "String"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
internalMappers.Fish = {
|
||||
required: false,
|
||||
serializedName: "Fish",
|
||||
type: {
|
||||
name: "Composite",
|
||||
polymorphicDiscriminator: {
|
||||
serializedName: "fish.type",
|
||||
clientName: "fishtype"
|
||||
},
|
||||
uberParent: "Fish",
|
||||
className: "Fish",
|
||||
modelProperties: {
|
||||
species: {
|
||||
required: false,
|
||||
serializedName: "species",
|
||||
type: {
|
||||
name: "String"
|
||||
}
|
||||
},
|
||||
length: {
|
||||
required: true,
|
||||
serializedName: "length",
|
||||
type: {
|
||||
name: "Number"
|
||||
}
|
||||
},
|
||||
siblings: {
|
||||
required: false,
|
||||
serializedName: "siblings",
|
||||
type: {
|
||||
name: "Sequence",
|
||||
element: {
|
||||
required: false,
|
||||
serializedName: "FishElementType",
|
||||
type: {
|
||||
name: "Composite",
|
||||
polymorphicDiscriminator: {
|
||||
serializedName: "fish.type",
|
||||
clientName: "fishtype"
|
||||
},
|
||||
uberParent: "Fish",
|
||||
className: "Fish"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
fishtype: {
|
||||
required: true,
|
||||
serializedName: "fish\\.type",
|
||||
type: {
|
||||
name: "String"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
internalMappers.Invoice = {
|
||||
required: false,
|
||||
serializedName: "Invoice",
|
||||
type: {
|
||||
name: "Composite",
|
||||
className: "Invoice",
|
||||
modelProperties: {
|
||||
invId: {
|
||||
serializedName: "invoiceId",
|
||||
required: true,
|
||||
type: {
|
||||
name: "Number"
|
||||
}
|
||||
},
|
||||
invDate: {
|
||||
serializedName: "invDate",
|
||||
required: false,
|
||||
type: {
|
||||
name: "Date"
|
||||
}
|
||||
},
|
||||
invProducts: {
|
||||
serializedName: "invProducts",
|
||||
required: false,
|
||||
type: {
|
||||
name: "Sequence",
|
||||
element: {
|
||||
type: {
|
||||
name: "Dictionary",
|
||||
value: {
|
||||
type: {
|
||||
name: "Composite",
|
||||
className: "Product"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
internalMappers.Pet = {
|
||||
required: false,
|
||||
serializedName: "pet",
|
||||
type: {
|
||||
name: "Composite",
|
||||
className: "Pet",
|
||||
polymorphicDiscriminator: "pet.type",
|
||||
modelProperties: {
|
||||
id: {
|
||||
required: false,
|
||||
serializedName: "id",
|
||||
type: {
|
||||
name: "Number"
|
||||
}
|
||||
},
|
||||
name: {
|
||||
required: false,
|
||||
serializedName: "name",
|
||||
type: {
|
||||
name: "String"
|
||||
}
|
||||
},
|
||||
pettype: {
|
||||
required: true,
|
||||
serializedName: "pet\\.type",
|
||||
type: {
|
||||
name: "String"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
internalMappers.PetGallery = {
|
||||
required: false,
|
||||
serializedName: "PetGallery",
|
||||
type: {
|
||||
name: "Composite",
|
||||
className: "PetGallery",
|
||||
modelProperties: {
|
||||
id: {
|
||||
required: false,
|
||||
serializedName: "id",
|
||||
type: {
|
||||
name: "Number"
|
||||
}
|
||||
},
|
||||
name: {
|
||||
required: false,
|
||||
serializedName: "name",
|
||||
type: {
|
||||
name: "String"
|
||||
}
|
||||
},
|
||||
pets: {
|
||||
required: false,
|
||||
serializedName: "pets",
|
||||
type: {
|
||||
name: "Sequence",
|
||||
element: {
|
||||
required: false,
|
||||
serializedName: "petElementType",
|
||||
type: {
|
||||
name: "Composite",
|
||||
polymorphicDiscriminator: "pet.type",
|
||||
uberParent: "Pet",
|
||||
className: "Pet"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
internalMappers.Product = {
|
||||
required: false,
|
||||
serializedName: "Product",
|
||||
type: {
|
||||
name: "Composite",
|
||||
className: "Product",
|
||||
modelProperties: {
|
||||
id: {
|
||||
serializedName: "id",
|
||||
constraints: {},
|
||||
required: true,
|
||||
type: {
|
||||
name: "Number"
|
||||
}
|
||||
},
|
||||
name: {
|
||||
serializedName: "name",
|
||||
required: true,
|
||||
type: {
|
||||
name: "String"
|
||||
}
|
||||
},
|
||||
provisioningState: {
|
||||
serializedName: "properties.provisioningState",
|
||||
required: false,
|
||||
type: {
|
||||
name: "Enum",
|
||||
allowedValues: ["Creating", "Failed", "Succeeded"]
|
||||
}
|
||||
},
|
||||
tags: {
|
||||
serializedName: "tags",
|
||||
required: false,
|
||||
type: {
|
||||
name: "Dictionary",
|
||||
value: {
|
||||
type: {
|
||||
name: "String"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
dispatchTime: {
|
||||
serializedName: "dispatchTime",
|
||||
required: false,
|
||||
type: {
|
||||
name: "DateTime"
|
||||
}
|
||||
},
|
||||
invoiceInfo: {
|
||||
serializedName: "invoiceInfo",
|
||||
required: false,
|
||||
type: {
|
||||
name: "Composite",
|
||||
className: "Invoice"
|
||||
}
|
||||
},
|
||||
subProducts: {
|
||||
serializedName: "subProducts",
|
||||
required: false,
|
||||
type: {
|
||||
name: "Sequence",
|
||||
element: {
|
||||
type: {
|
||||
name: "Composite",
|
||||
className: "SubProduct"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
internalMappers.ProductListResult = {
|
||||
required: false,
|
||||
serializedName: "ProductListResult",
|
||||
type: {
|
||||
name: "Composite",
|
||||
className: "ProductListResult",
|
||||
modelProperties: {
|
||||
value: {
|
||||
serializedName: "",
|
||||
required: false,
|
||||
type: {
|
||||
name: "Sequence",
|
||||
element: {
|
||||
type: {
|
||||
name: "Composite",
|
||||
className: "Product"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
internalMappers.ProductListResultNextLink = {
|
||||
required: false,
|
||||
serializedName: "ProductListResultNextLink",
|
||||
type: {
|
||||
name: "Composite",
|
||||
className: "ProductListResultNextLink",
|
||||
modelProperties: {
|
||||
value: {
|
||||
serializedName: "",
|
||||
required: false,
|
||||
type: {
|
||||
name: "Sequence",
|
||||
element: {
|
||||
type: {
|
||||
name: "Composite",
|
||||
className: "Product"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
nextLink: {
|
||||
serializedName: "nextLink",
|
||||
required: false,
|
||||
type: {
|
||||
name: "String"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
internalMappers.SawShark = {
|
||||
required: false,
|
||||
serializedName: "sawshark",
|
||||
type: {
|
||||
name: "Composite",
|
||||
className: "Sawshark",
|
||||
modelProperties: {
|
||||
species: {
|
||||
required: false,
|
||||
serializedName: "species",
|
||||
type: {
|
||||
name: "String"
|
||||
}
|
||||
},
|
||||
length: {
|
||||
required: true,
|
||||
serializedName: "length",
|
||||
type: {
|
||||
name: "Number"
|
||||
}
|
||||
},
|
||||
siblings: {
|
||||
required: false,
|
||||
serializedName: "siblings",
|
||||
type: {
|
||||
name: "Sequence",
|
||||
element: {
|
||||
required: false,
|
||||
serializedName: "FishElementType",
|
||||
type: {
|
||||
name: "Composite",
|
||||
polymorphicDiscriminator: {
|
||||
serializedName: "fish.type",
|
||||
clientName: "fishtype"
|
||||
},
|
||||
uberParent: "Fish",
|
||||
className: "Fish"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
fishtype: {
|
||||
required: true,
|
||||
serializedName: "fish\\.type",
|
||||
type: {
|
||||
name: "String"
|
||||
}
|
||||
},
|
||||
age: {
|
||||
required: false,
|
||||
serializedName: "age",
|
||||
type: {
|
||||
name: "Number"
|
||||
}
|
||||
},
|
||||
birthday: {
|
||||
required: true,
|
||||
serializedName: "birthday",
|
||||
type: {
|
||||
name: "DateTime"
|
||||
}
|
||||
},
|
||||
picture: {
|
||||
required: false,
|
||||
serializedName: "picture",
|
||||
type: {
|
||||
name: "ByteArray"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
internalMappers.Shark = {
|
||||
required: false,
|
||||
serializedName: "shark",
|
||||
type: {
|
||||
name: "Composite",
|
||||
className: "Shark",
|
||||
modelProperties: {
|
||||
species: {
|
||||
required: false,
|
||||
serializedName: "species",
|
||||
type: {
|
||||
name: "String"
|
||||
}
|
||||
},
|
||||
length: {
|
||||
required: true,
|
||||
serializedName: "length",
|
||||
type: {
|
||||
name: "Number"
|
||||
}
|
||||
},
|
||||
siblings: {
|
||||
required: false,
|
||||
serializedName: "siblings",
|
||||
type: {
|
||||
name: "Sequence",
|
||||
element: {
|
||||
required: false,
|
||||
serializedName: "FishElementType",
|
||||
type: {
|
||||
name: "Composite",
|
||||
polymorphicDiscriminator: {
|
||||
serializedName: "fish.type",
|
||||
clientName: "fishtype"
|
||||
},
|
||||
uberParent: "Fish",
|
||||
className: "Fish"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
fishtype: {
|
||||
required: true,
|
||||
serializedName: "fish\\.type",
|
||||
type: {
|
||||
name: "String"
|
||||
}
|
||||
},
|
||||
age: {
|
||||
required: false,
|
||||
serializedName: "age",
|
||||
type: {
|
||||
name: "Number"
|
||||
}
|
||||
},
|
||||
birthday: {
|
||||
required: true,
|
||||
serializedName: "birthday",
|
||||
type: {
|
||||
name: "DateTime"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
internalMappers.SubProduct = {
|
||||
required: false,
|
||||
serializedName: "SubProduct",
|
||||
type: {
|
||||
name: "Composite",
|
||||
className: "SubProduct",
|
||||
modelProperties: {
|
||||
subId: {
|
||||
serializedName: "subId",
|
||||
required: true,
|
||||
type: {
|
||||
name: "Number"
|
||||
}
|
||||
},
|
||||
subName: {
|
||||
serializedName: "subName",
|
||||
required: true,
|
||||
type: {
|
||||
name: "String"
|
||||
}
|
||||
},
|
||||
provisioningState: {
|
||||
serializedName: "provisioningState",
|
||||
required: false,
|
||||
type: {
|
||||
name: "Enum",
|
||||
allowedValues: ["Creating", "Failed", "Succeeded"]
|
||||
}
|
||||
},
|
||||
makeTime: {
|
||||
serializedName: "makeTime",
|
||||
required: false,
|
||||
type: {
|
||||
name: "DateTime"
|
||||
}
|
||||
},
|
||||
invoiceInfo: {
|
||||
serializedName: "invoiceInfo",
|
||||
required: false,
|
||||
type: {
|
||||
name: "Composite",
|
||||
className: "Invoice"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
internalMappers.discriminators = {
|
||||
"Fish": internalMappers.Fish,
|
||||
"Fish.shark": internalMappers.Shark,
|
||||
"Fish.sawshark": internalMappers.SawShark,
|
||||
"Pet": internalMappers.Pet,
|
||||
"Pet.Cat": internalMappers.Cat,
|
||||
"Pet.Dog": internalMappers.Dog
|
||||
};
|
||||
exports.Mappers = internalMappers;
|
||||
//# sourceMappingURL=mappers.js.map
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for
|
||||
* license information.
|
||||
*
|
||||
* Code generated by Microsoft (R) AutoRest Code Generator 0.14.0.0
|
||||
* Changes may cause incorrect behavior and will be lost if the code is
|
||||
* regenerated.
|
||||
*/
|
||||
/* jshint latedef:false */
|
||||
/* jshint forin:false */
|
||||
/* jshint noempty:false */
|
||||
'use strict';
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const msRest = require("../../../../lib/msRest");
|
||||
const mappers_1 = require("./models/mappers");
|
||||
/**
|
||||
* @class
|
||||
* Initializes a new instance of the TestClient class.
|
||||
* @constructor
|
||||
*
|
||||
* @param {string} [baseUri] - The base URI of the service.
|
||||
*
|
||||
* @param {object} [options] - The parameter options
|
||||
*
|
||||
* @param {Array} [options.filters] - Filters to be added to the request pipeline
|
||||
*
|
||||
* @param {object} [options.requestOptions] - Options for the underlying request object
|
||||
* {@link https://github.com/request/request#requestoptions-callback Options doc}
|
||||
*
|
||||
* @param {bool} [options.noRetryPolicy] - If set to true, turn off default retry policy
|
||||
*/
|
||||
class TestClient extends msRest.ServiceClient {
|
||||
constructor(baseUri, options) {
|
||||
if (!options)
|
||||
options = {};
|
||||
super(undefined, options);
|
||||
this.baseUri = baseUri;
|
||||
if (!this.baseUri) {
|
||||
this.baseUri = 'https://management.azure.com';
|
||||
}
|
||||
if (!this.acceptLanguage) {
|
||||
this.acceptLanguage = 'en-US';
|
||||
}
|
||||
this.serializer = new msRest.Serializer(mappers_1.Mappers);
|
||||
}
|
||||
}
|
||||
exports.TestClient = TestClient;
|
||||
//# sourceMappingURL=testClient.js.map
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"testClient.js","sourceRoot":"","sources":["../../../../../test/data/TestClient/lib/testClient.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,0BAA0B;AAC1B,wBAAwB;AACxB,0BAA0B;AAE1B,YAAY,CAAC;;AAEb,iDAAiD;AACjD,8CAA2C;AAE3C;;;;;;;;;;;;;;;GAeG;AAEH,gBAAiB,SAAQ,MAAM,CAAC,aAAa;IAK3C,YAAY,OAAe,EAAE,OAAqC;QAChE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;QAC3B,KAAK,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QAC1B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;YAClB,IAAI,CAAC,OAAO,GAAG,8BAA8B,CAAC;QAChD,CAAC;QAED,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC;YACzB,IAAI,CAAC,cAAc,GAAG,OAAO,CAAC;QAChC,CAAC;QACD,IAAI,CAAC,UAAU,GAAG,IAAI,MAAM,CAAC,UAAU,CAAC,iBAAO,CAAC,CAAC;IACnD,CAAC;CACF;AAEQ,gCAAU"}
|
|
@ -0,0 +1,41 @@
|
|||
"use strict";
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const assert = require("assert");
|
||||
const webResource_1 = require("../lib/webResource");
|
||||
const httpOperationResponse_1 = require("../lib/httpOperationResponse");
|
||||
const logFilter_1 = require("../lib/filters/logFilter");
|
||||
const node_fetch_1 = require("node-fetch");
|
||||
describe("Log filter", () => {
|
||||
it("should log messages when a logger object is provided", (done) => {
|
||||
const expected = `>> Request: {
|
||||
"headers": {},
|
||||
"rawResponse": false,
|
||||
"url": "https://foo.com",
|
||||
"method": "PUT",
|
||||
"body": {
|
||||
"a": 1
|
||||
}
|
||||
}
|
||||
>> Response status code: 200
|
||||
>> Body: null
|
||||
`;
|
||||
let output = "";
|
||||
const logger = (message) => { output += message + "\n"; };
|
||||
const lf = new logFilter_1.LogFilter(logger);
|
||||
const req = new webResource_1.WebResource("https://foo.com", "PUT", { "a": 1 });
|
||||
const res = new node_fetch_1.Response();
|
||||
const opRes = new httpOperationResponse_1.HttpOperationResponse(req, res, res.body);
|
||||
lf.after(opRes).then(() => {
|
||||
//console.dir(output, { depth: null });
|
||||
//console.log(">>>>>>>");
|
||||
//console.dir(expected);
|
||||
assert.deepEqual(output, expected);
|
||||
done();
|
||||
}).catch((err) => {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
});
|
||||
//# sourceMappingURL=logFilterTests.js.map
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"logFilterTests.js","sourceRoot":"","sources":["../../test/logFilterTests.ts"],"names":[],"mappings":";AAAA,4DAA4D;AAC5D,+FAA+F;;AAG/F,iCAAiC;AACjC,oDAAiD;AACjD,wEAAqE;AACrE,wDAAqD;AAErD,2CAAsC;AAEtC,QAAQ,CAAC,YAAY,EAAE;IAErB,EAAE,CAAC,sDAAsD,EAAE,CAAC,IAAI;QAC9D,MAAM,QAAQ,GAAG;;;;;;;;;;;CAWpB,CAAC;QACE,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,MAAM,MAAM,GAAa,CAAC,OAAe,OAAa,MAAM,IAAI,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAClF,MAAM,EAAE,GAAG,IAAI,qBAAS,CAAC,MAAM,CAAC,CAAC;QACjC,MAAM,GAAG,GAAG,IAAI,yBAAW,CAAC,iBAAiB,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;QAClE,MAAM,GAAG,GAAG,IAAI,qBAAQ,EAAE,CAAC;QAC3B,MAAM,KAAK,GAAG,IAAI,6CAAqB,CAAC,GAAG,EAAE,GAAU,EAAE,GAAG,CAAC,IAAW,CAAC,CAAC;QAC1E,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC;YACnB,uCAAuC;YACvC,yBAAyB;YACzB,wBAAwB;YACxB,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;YACnC,IAAI,EAAE,CAAC;QACT,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAU;YAClB,IAAI,CAAC,GAAG,CAAC,CAAC;QACZ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@ -0,0 +1,746 @@
|
|||
"use strict";
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const assert = require("assert");
|
||||
const moment = require("moment");
|
||||
const msRest = require("../lib/msRest");
|
||||
const should = require("should");
|
||||
const testClient_1 = require("./data/TestClient/lib/testClient");
|
||||
const mappers_1 = require("./data/Testclient/lib/models/mappers");
|
||||
let Serializer = new msRest.Serializer({});
|
||||
let valid_uuid = "ceaafd1e-f936-429f-bbfc-82ee75dddc33";
|
||||
describe("msrest", function () {
|
||||
describe("serializeObject", function () {
|
||||
it("should correctly serialize a Date Object", function (done) {
|
||||
let dateObj = new Date("2015-01-01");
|
||||
let dateISO = "2015-01-01T00:00:00.000Z";
|
||||
msRest.serializeObject(dateObj).should.equal(dateISO);
|
||||
done();
|
||||
});
|
||||
it("should correctly serialize a Date object with max value", function (done) {
|
||||
let serializedDateString = msRest.serializeObject(new Date("9999-12-31T23:59:59-12:00"));
|
||||
serializedDateString.should.equal("+010000-01-01T11:59:59.000Z");
|
||||
done();
|
||||
});
|
||||
it("should correctly serialize a Buffer Object", function (done) {
|
||||
let bufferObj = new Buffer("Javascript");
|
||||
let base64str = "SmF2YXNjcmlwdA==";
|
||||
msRest.serializeObject(bufferObj).should.equal(base64str);
|
||||
done();
|
||||
});
|
||||
it("should correctly serialize Primitive types", function (done) {
|
||||
msRest.serializeObject(true).should.equal(true);
|
||||
msRest.serializeObject(false).should.equal(false);
|
||||
msRest.serializeObject("true").should.equal("true");
|
||||
msRest.serializeObject(1).should.equal(1);
|
||||
msRest.serializeObject(100.0123).should.equal(100.0123);
|
||||
assert.equal(msRest.serializeObject(null), null);
|
||||
done();
|
||||
});
|
||||
it("should correctly serialize an empty array and an empty dictionary", function (done) {
|
||||
assert.deepEqual(msRest.serializeObject([]), []);
|
||||
assert.deepEqual(msRest.serializeObject({}), {});
|
||||
done();
|
||||
});
|
||||
it("should correctly serialize a complex JSON object", function (done) {
|
||||
let o1 = {
|
||||
"p1": "value1",
|
||||
"p2": "value2",
|
||||
"top-buf": new Buffer("top string", "utf-8"),
|
||||
"top-date": new Date("2014"),
|
||||
"top-dates": [new Date("1900"), new Date("1901")],
|
||||
"insider": {
|
||||
"insider-buf": new Buffer("insider string", "utf-8"),
|
||||
"insider-date": new Date("2015"),
|
||||
"insider-dates": [new Date("2100"), new Date("2101")],
|
||||
"insider-dictionary": {
|
||||
"k1": new Date("2015"),
|
||||
"k2": new Date("2016"),
|
||||
"k3": new Date("2017")
|
||||
},
|
||||
"top-complex": {
|
||||
"id": 1,
|
||||
"name": "Joey",
|
||||
"age": 23.36,
|
||||
"male": true,
|
||||
"birthday": "1992-01-01T00:00:00.000Z",
|
||||
"anniversary": new Date("2013-12-08"),
|
||||
"memory": new Buffer("Yadadadada")
|
||||
}
|
||||
}
|
||||
};
|
||||
let o2 = {
|
||||
p1: "value1",
|
||||
p2: "value2",
|
||||
"top-buf": "dG9wIHN0cmluZw==",
|
||||
"top-date": "2014-01-01T00:00:00.000Z",
|
||||
"top-dates": [
|
||||
"1900-01-01T00:00:00.000Z",
|
||||
"1901-01-01T00:00:00.000Z"
|
||||
],
|
||||
insider: {
|
||||
"insider-buf": "aW5zaWRlciBzdHJpbmc=",
|
||||
"insider-date": "2015-01-01T00:00:00.000Z",
|
||||
"insider-dates": [
|
||||
"2100-01-01T00:00:00.000Z",
|
||||
"2101-01-01T00:00:00.000Z"
|
||||
],
|
||||
"insider-dictionary": {
|
||||
k1: "2015-01-01T00:00:00.000Z",
|
||||
k2: "2016-01-01T00:00:00.000Z",
|
||||
k3: "2017-01-01T00:00:00.000Z"
|
||||
},
|
||||
"top-complex": {
|
||||
id: 1,
|
||||
name: "Joey",
|
||||
age: 23.36,
|
||||
male: true,
|
||||
birthday: "1992-01-01T00:00:00.000Z",
|
||||
anniversary: "2013-12-08T00:00:00.000Z",
|
||||
memory: "WWFkYWRhZGFkYQ=="
|
||||
}
|
||||
}
|
||||
};
|
||||
assert.deepEqual(msRest.serializeObject(o1), o2);
|
||||
done();
|
||||
});
|
||||
});
|
||||
describe("serialize", function () {
|
||||
let invalid_uuid = "abcd-efgd90-90890jkh";
|
||||
it("should correctly serialize a string", function (done) {
|
||||
let mapper = { type: { name: "String" }, required: false, serializedName: "string" };
|
||||
let serializedObject = Serializer.serialize(mapper, "foo", "stringBody");
|
||||
serializedObject.should.equal("foo");
|
||||
done();
|
||||
});
|
||||
it("should correctly serialize a uuid", function (done) {
|
||||
let mapper = { type: { name: "Uuid" }, required: false, serializedName: "Uuid" };
|
||||
let serializedObject = Serializer.serialize(mapper, valid_uuid, "uuidBody");
|
||||
serializedObject.should.equal(valid_uuid);
|
||||
done();
|
||||
});
|
||||
it("should throw an error if the value is not a valid Uuid", function (done) {
|
||||
let mapper = { type: { name: "Uuid" }, required: false, serializedName: "Uuid" };
|
||||
try {
|
||||
Serializer.serialize(mapper, invalid_uuid, "uuidBody");
|
||||
}
|
||||
catch (error) {
|
||||
error.message.should.match(/.*with value.*must be of type string and a valid uuid/ig);
|
||||
done();
|
||||
}
|
||||
});
|
||||
it("should correctly serialize a number", function (done) {
|
||||
let mapper = { type: { name: "Number" }, required: false, serializedName: "Number" };
|
||||
let serializedObject = Serializer.serialize(mapper, 1.506, "stringBody");
|
||||
serializedObject.should.equal(1.506);
|
||||
done();
|
||||
});
|
||||
it("should correctly serialize a boolean", function (done) {
|
||||
let mapper = { type: { name: "Boolean" }, required: false, serializedName: "Boolean" };
|
||||
let serializedObject = Serializer.serialize(mapper, false, "stringBody");
|
||||
serializedObject.should.equal(false);
|
||||
done();
|
||||
});
|
||||
it("should correctly serialize an Enum", function (done) {
|
||||
let mapper = { type: { name: "Enum", allowedValues: [1, 2, 3, 4] }, required: false, serializedName: "Enum" };
|
||||
let serializedObject = Serializer.serialize(mapper, 1, "enumBody");
|
||||
serializedObject.should.equal(1);
|
||||
done();
|
||||
});
|
||||
it("should throw an error if the value is not valid for an Enum", function (done) {
|
||||
let mapper = { type: { name: "Enum", allowedValues: [1, 2, 3, 4] }, required: false, serializedName: "Enum" };
|
||||
try {
|
||||
Serializer.serialize(mapper, 6, "enumBody");
|
||||
}
|
||||
catch (error) {
|
||||
error.message.should.match(/6 is not a valid value for enumBody\. The valid values are: \[1,2,3,4\]/ig);
|
||||
done();
|
||||
}
|
||||
});
|
||||
it("should correctly serialize a Buffer Object", function (done) {
|
||||
let mapper = { type: { name: "ByteArray" }, required: false, serializedName: "ByteArray" };
|
||||
let bufferObj = new Buffer("Javascript");
|
||||
let base64str = "SmF2YXNjcmlwdA==";
|
||||
let serializedObject = Serializer.serialize(mapper, bufferObj, "stringBody");
|
||||
serializedObject.should.equal(base64str);
|
||||
done();
|
||||
});
|
||||
it("should correctly serialize a Date Object", function (done) {
|
||||
let dateObj = new Date("2015-01-01");
|
||||
let dateISO = "2015-01-01";
|
||||
let mapper = { type: { name: "Date" }, required: false, serializedName: "Date" };
|
||||
Serializer.serialize(mapper, dateObj, "dateObj").should.equal(dateISO);
|
||||
done();
|
||||
});
|
||||
it("should correctly serialize a Date object with max value", function (done) {
|
||||
let mapper = { type: { name: "DateTime" }, required: false, serializedName: "DateTime" };
|
||||
let serializedDateString = Serializer.serialize(mapper, new Date("9999-12-31T23:59:59-12:00"), "dateTimeObj");
|
||||
should.equal(serializedDateString, "+010000-01-01T11:59:59.000Z");
|
||||
done();
|
||||
});
|
||||
it("should correctly serialize a Date object with max value and format UnixTime", function (done) {
|
||||
let mapper = { type: { name: "UnixTime" }, required: false, serializedName: "UnixTime" };
|
||||
let serializedDate = Serializer.serialize(mapper, new Date("9999-12-31T23:59:59-12:00"), "dateTimeObj");
|
||||
serializedDate.should.equal(253402343999);
|
||||
done();
|
||||
});
|
||||
it("should correctly serialize a string in DateTimeRfc1123", function (done) {
|
||||
let mapper = { type: { name: "DateTimeRfc1123" }, required: false, serializedName: "DateTimeRfc1123" };
|
||||
let rfc = new Date("Mon, 01 Jan 0001 00:00:00 GMT");
|
||||
let serializedDateString = Serializer.serialize(mapper, rfc, "dateTimeObj");
|
||||
serializedDateString.should.equal("Mon, 01 Jan 2001 00:00:00 GMT");
|
||||
done();
|
||||
});
|
||||
it("should correctly serialize a duration object", function (done) {
|
||||
let mapper = { type: { name: "TimeSpan" }, required: false, serializedName: "TimeSpan" };
|
||||
let duration = moment.duration({ days: 123, hours: 22, minutes: 14, seconds: 12, milliseconds: 11 });
|
||||
let serializedDateString = Serializer.serialize(mapper, duration, "dateTimeObj");
|
||||
serializedDateString.should.equal("P123DT22H14M12.010999999998603S");
|
||||
done();
|
||||
});
|
||||
it("should correctly serialize an array of primitives", function (done) {
|
||||
let mapper = {
|
||||
required: false,
|
||||
serializedName: "Sequence",
|
||||
type: {
|
||||
name: "Sequence",
|
||||
element: {
|
||||
type: { name: "String" },
|
||||
required: true,
|
||||
serializedName: "sequenceElement"
|
||||
}
|
||||
}
|
||||
};
|
||||
let array = ["One", "Two", "three"];
|
||||
let serializedArray = Serializer.serialize(mapper, array, "arrayObj");
|
||||
assert.deepEqual(array, serializedArray);
|
||||
done();
|
||||
});
|
||||
it("should correctly serialize an array of array of primitives", function (done) {
|
||||
let mapper = {
|
||||
required: false,
|
||||
serializedName: "Sequence",
|
||||
type: {
|
||||
name: "Sequence",
|
||||
element: {
|
||||
required: true,
|
||||
serializedName: "sequenceElement",
|
||||
type: {
|
||||
name: "Sequence",
|
||||
element: {
|
||||
required: true,
|
||||
serializedName: "sequenceElement",
|
||||
type: {
|
||||
name: "Number"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
let array = [[1], [2], [1, 2, 3]];
|
||||
let serializedArray = Serializer.serialize(mapper, array, "arrayObj");
|
||||
assert.deepEqual(array, serializedArray);
|
||||
done();
|
||||
});
|
||||
it("should correctly serialize an array of dictionary of primitives", function (done) {
|
||||
let mapper = {
|
||||
required: false,
|
||||
serializedName: "Sequence",
|
||||
type: {
|
||||
name: "Sequence",
|
||||
element: {
|
||||
required: true,
|
||||
serializedName: "sequenceElement",
|
||||
type: {
|
||||
name: "Dictionary",
|
||||
value: {
|
||||
required: true,
|
||||
serializedName: "valueElement",
|
||||
type: {
|
||||
name: "Boolean"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
let array = [{ 1: true }, { 2: false }, { 1: true, 2: false, 3: true }];
|
||||
let serializedArray = Serializer.serialize(mapper, array, "arrayObj");
|
||||
assert.deepEqual(array, serializedArray);
|
||||
done();
|
||||
});
|
||||
it("should correctly serialize a dictionary of primitives", function (done) {
|
||||
let mapper = {
|
||||
required: false,
|
||||
serializedName: "Dictionary",
|
||||
type: {
|
||||
name: "Dictionary",
|
||||
value: {
|
||||
required: true,
|
||||
serializedName: "valueElement",
|
||||
type: {
|
||||
name: "String"
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
let dict = { 1: "One", 2: "Two", 3: "three" };
|
||||
let serializedDictionary = Serializer.serialize(mapper, dict, "dictObj");
|
||||
assert.deepEqual(dict, serializedDictionary);
|
||||
done();
|
||||
});
|
||||
it("should correctly serialize a dictionary of array of primitives", function (done) {
|
||||
let mapper = {
|
||||
required: false,
|
||||
serializedName: "Dictionary",
|
||||
type: {
|
||||
name: "Dictionary",
|
||||
value: {
|
||||
required: true,
|
||||
serializedName: "valueElement",
|
||||
type: {
|
||||
name: "Sequence",
|
||||
element: {
|
||||
required: true,
|
||||
serializedName: "sequenceElement",
|
||||
type: {
|
||||
name: "Number"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
let dict = { "One": [1], "Two": [1, 2], "three": [1, 2, 3] };
|
||||
let serializedDictionary = Serializer.serialize(mapper, dict, "dictObj");
|
||||
assert.deepEqual(dict, serializedDictionary);
|
||||
done();
|
||||
});
|
||||
it("should correctly serialize a dictionary of dictionary of primitives", function (done) {
|
||||
let mapper = {
|
||||
required: false,
|
||||
serializedName: "Dictionary",
|
||||
type: {
|
||||
name: "Dictionary",
|
||||
value: {
|
||||
required: true,
|
||||
serializedName: "valueElement",
|
||||
type: {
|
||||
name: "Dictionary",
|
||||
value: {
|
||||
required: true,
|
||||
serializedName: "valueElement",
|
||||
type: {
|
||||
name: "Boolean"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
let dict = { 1: { "One": true }, 2: { "Two": false }, 3: { "three": true } };
|
||||
let serializedDictionary = Serializer.serialize(mapper, dict, "dictObj");
|
||||
assert.deepEqual(dict, serializedDictionary);
|
||||
done();
|
||||
});
|
||||
it("should correctly serialize a composite type", function (done) {
|
||||
let client = new testClient_1.TestClient("http://localhost:9090");
|
||||
let mapper = mappers_1.Mappers.Product;
|
||||
let productObj = {
|
||||
id: 101,
|
||||
name: "TestProduct",
|
||||
provisioningState: "Succeeded",
|
||||
tags: {
|
||||
tag1: "value1",
|
||||
tag2: "value2"
|
||||
},
|
||||
dispatchTime: new Date("2015-01-01T12:35:36.009Z"),
|
||||
invoiceInfo: {
|
||||
invId: 1002,
|
||||
invDate: "2015-12-25",
|
||||
invProducts: [
|
||||
{
|
||||
"Product1": {
|
||||
id: 101,
|
||||
name: "TestProduct"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Product2": {
|
||||
id: 104,
|
||||
name: "TestProduct1"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
subProducts: [
|
||||
{
|
||||
subId: 102,
|
||||
subName: "SubProduct1",
|
||||
makeTime: new Date("2015-12-21T01:01:01"),
|
||||
invoiceInfo: {
|
||||
invId: 1002,
|
||||
invDate: "2015-12-25"
|
||||
}
|
||||
},
|
||||
{
|
||||
subId: 103,
|
||||
subName: "SubProduct2",
|
||||
makeTime: new Date("2015-12-21T01:01:01"),
|
||||
invoiceInfo: {
|
||||
invId: 1003,
|
||||
invDate: "2015-12-25"
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
let serializedProduct = client.serializer.serialize(mapper, productObj, "productObject");
|
||||
for (let prop in serializedProduct) {
|
||||
if (prop === "properties") {
|
||||
serializedProduct[prop].provisioningState.should.equal(productObj.provisioningState);
|
||||
}
|
||||
else if (prop === "id") {
|
||||
serializedProduct[prop].should.equal(productObj.id);
|
||||
}
|
||||
else if (prop === "name") {
|
||||
serializedProduct[prop].should.equal(productObj.name);
|
||||
}
|
||||
else if (prop === "tags") {
|
||||
JSON.stringify(serializedProduct[prop]).should.equal(JSON.stringify(productObj.tags));
|
||||
}
|
||||
else if (prop === "dispatchTime") {
|
||||
JSON.stringify(serializedProduct[prop]).should.equal(JSON.stringify(productObj.dispatchTime));
|
||||
}
|
||||
else if (prop === "invoiceInfo") {
|
||||
(JSON.stringify(serializedProduct[prop]).length - JSON.stringify(productObj.invoiceInfo).length).should.equal(4);
|
||||
}
|
||||
else if (prop === "subProducts") {
|
||||
(JSON.stringify(serializedProduct[prop]).length - JSON.stringify(productObj.subProducts).length).should.equal(8);
|
||||
}
|
||||
}
|
||||
done();
|
||||
});
|
||||
it("should correctly serialize object version of polymorphic discriminator", function (done) {
|
||||
let client = new testClient_1.TestClient("http://localhost:9090");
|
||||
let mapper = mappers_1.Mappers.SawShark;
|
||||
let sawshark = {
|
||||
"fishtype": "sawshark",
|
||||
"age": 22,
|
||||
"birthday": new Date("2012-01-05T01:00:00Z"),
|
||||
"species": "king",
|
||||
"length": 1.0,
|
||||
"picture": new Buffer([255, 255, 255, 255, 254]),
|
||||
"siblings": [
|
||||
{
|
||||
"fishtype": "shark",
|
||||
"age": 6,
|
||||
"birthday": new Date("2012-01-05T01:00:00Z"),
|
||||
"length": 20.0,
|
||||
"species": "predator"
|
||||
},
|
||||
{
|
||||
"fishtype": "sawshark",
|
||||
"age": 105,
|
||||
"birthday": new Date("1900-01-05T01:00:00Z"),
|
||||
"length": 10.0,
|
||||
"picture": new Buffer([255, 255, 255, 255, 254]),
|
||||
"species": "dangerous"
|
||||
}
|
||||
]
|
||||
};
|
||||
let serializedSawshark = client.serializer.serialize(mapper, sawshark, "result");
|
||||
serializedSawshark.age.should.equal(22);
|
||||
serializedSawshark["fish.type"].should.equal("sawshark");
|
||||
serializedSawshark.siblings.length.should.equal(2);
|
||||
serializedSawshark.siblings[0]["fish.type"].should.equal("shark");
|
||||
serializedSawshark.siblings[0].age.should.equal(6);
|
||||
serializedSawshark.siblings[0].birthday.should.equal(new Date("2012-01-05T01:00:00Z").toISOString());
|
||||
serializedSawshark.siblings[1]["fish.type"].should.equal("sawshark");
|
||||
serializedSawshark.siblings[1].age.should.equal(105);
|
||||
serializedSawshark.siblings[1].birthday.should.equal(new Date("1900-01-05T01:00:00Z").toISOString());
|
||||
serializedSawshark.siblings[1].picture.should.equal("//////4=");
|
||||
serializedSawshark.picture.should.equal("//////4=");
|
||||
done();
|
||||
});
|
||||
it("should correctly serialize string version of polymorphic discriminator", function (done) {
|
||||
let client = new testClient_1.TestClient("http://localhost:9090");
|
||||
let mapper = mappers_1.Mappers.PetGallery;
|
||||
let petgallery = {
|
||||
"id": 1,
|
||||
"name": "Fav pet gallery",
|
||||
"pets": [
|
||||
{
|
||||
"id": 2,
|
||||
"name": "moti",
|
||||
"food": "buiscuit",
|
||||
"pet.type": "Dog",
|
||||
"pettype": "Dog"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"name": "billa",
|
||||
"color": "red",
|
||||
"pet.type": "Cat",
|
||||
"pettype": "Cat" // In string version the user has to pass the actual property with dot and the normalized one.
|
||||
}
|
||||
]
|
||||
};
|
||||
let serializedPetGallery = client.serializer.serialize(mapper, petgallery, "result");
|
||||
serializedPetGallery.id.should.equal(1);
|
||||
serializedPetGallery.name.should.equal("Fav pet gallery");
|
||||
serializedPetGallery.pets.length.should.equal(2);
|
||||
serializedPetGallery.pets[0]["pet.type"].should.equal("Dog");
|
||||
serializedPetGallery.pets[0].id.should.equal(2);
|
||||
serializedPetGallery.pets[0].name.should.equal("moti");
|
||||
serializedPetGallery.pets[0].food.should.equal("buiscuit");
|
||||
serializedPetGallery.pets[1]["pet.type"].should.equal("Cat");
|
||||
serializedPetGallery.pets[1].id.should.equal(3);
|
||||
serializedPetGallery.pets[1].name.should.equal("billa");
|
||||
serializedPetGallery.pets[1].color.should.equal("red");
|
||||
done();
|
||||
});
|
||||
});
|
||||
describe("deserialize", function () {
|
||||
it("should correctly deserialize a uuid", function (done) {
|
||||
let mapper = { type: { name: "Uuid" }, required: false, serializedName: "Uuid" };
|
||||
let serializedObject = Serializer.deserialize(mapper, valid_uuid, "uuidBody");
|
||||
serializedObject.should.equal(valid_uuid);
|
||||
done();
|
||||
});
|
||||
it("should correctly deserialize a composite type", function (done) {
|
||||
let client = new testClient_1.TestClient("http://localhost:9090");
|
||||
let mapper = mappers_1.Mappers.Product;
|
||||
let responseBody = {
|
||||
id: 101,
|
||||
name: "TestProduct",
|
||||
properties: {
|
||||
provisioningState: "Succeeded"
|
||||
},
|
||||
tags: {
|
||||
tag1: "value1",
|
||||
tag2: "value2"
|
||||
},
|
||||
dispatchTime: new Date("2015-01-01T12:35:36.009Z"),
|
||||
invoiceInfo: {
|
||||
invoiceId: 1002,
|
||||
invDate: "2015-12-25",
|
||||
invProducts: [
|
||||
{
|
||||
"Product1": {
|
||||
id: 101,
|
||||
name: "TestProduct"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Product2": {
|
||||
id: 104,
|
||||
name: "TestProduct1"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
subProducts: [
|
||||
{
|
||||
subId: 102,
|
||||
subName: "SubProduct1",
|
||||
makeTime: new Date("2015-12-21T01:01:01"),
|
||||
invoiceInfo: {
|
||||
invoiceId: 1002,
|
||||
invDate: "2015-12-25"
|
||||
}
|
||||
},
|
||||
{
|
||||
subId: 103,
|
||||
subName: "SubProduct2",
|
||||
makeTime: new Date("2015-12-21T01:01:01"),
|
||||
invoiceInfo: {
|
||||
invoiceId: 1003,
|
||||
invDate: "2015-12-25"
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
let deserializedProduct = client.serializer.deserialize(mapper, responseBody, "responseBody");
|
||||
for (let prop in deserializedProduct) {
|
||||
if (prop === "provisioningState") {
|
||||
deserializedProduct.provisioningState.should.equal(responseBody.properties.provisioningState);
|
||||
}
|
||||
else if (prop === "id") {
|
||||
deserializedProduct[prop].should.equal(responseBody.id);
|
||||
}
|
||||
else if (prop === "name") {
|
||||
deserializedProduct[prop].should.equal(responseBody.name);
|
||||
}
|
||||
else if (prop === "tags") {
|
||||
JSON.stringify(deserializedProduct[prop]).should.equal(JSON.stringify(responseBody.tags));
|
||||
}
|
||||
else if (prop === "dispatchTime") {
|
||||
JSON.stringify(deserializedProduct[prop]).should.equal(JSON.stringify(responseBody.dispatchTime));
|
||||
}
|
||||
else if (prop === "invoiceInfo") {
|
||||
(JSON.stringify(deserializedProduct[prop]).length - JSON.stringify(responseBody.invoiceInfo).length).should.equal(10);
|
||||
}
|
||||
else if (prop === "subProducts") {
|
||||
(JSON.stringify(deserializedProduct[prop]).length - JSON.stringify(responseBody.subProducts).length).should.equal(20);
|
||||
}
|
||||
}
|
||||
done();
|
||||
});
|
||||
it("should correctly deserialize a pageable type without nextLink", function (done) {
|
||||
let client = new testClient_1.TestClient("http://localhost:9090");
|
||||
let mapper = mappers_1.Mappers.ProductListResult;
|
||||
let responseBody = {
|
||||
value: [
|
||||
{
|
||||
id: 101,
|
||||
name: "TestProduct",
|
||||
properties: {
|
||||
provisioningState: "Succeeded"
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 104,
|
||||
name: "TestProduct1",
|
||||
properties: {
|
||||
provisioningState: "Failed"
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
let deserializedProduct = client.serializer.deserialize(mapper, responseBody, "responseBody");
|
||||
(Array.isArray(deserializedProduct)).should.be.true;
|
||||
deserializedProduct.length.should.equal(2);
|
||||
for (let i = 0; i < deserializedProduct.length; i++) {
|
||||
if (i === 0) {
|
||||
deserializedProduct[i].id.should.equal(101);
|
||||
deserializedProduct[i].name.should.equal("TestProduct");
|
||||
deserializedProduct[i].provisioningState.should.equal("Succeeded");
|
||||
}
|
||||
else if (i === 1) {
|
||||
deserializedProduct[i].id.should.equal(104);
|
||||
deserializedProduct[i].name.should.equal("TestProduct1");
|
||||
deserializedProduct[i].provisioningState.should.equal("Failed");
|
||||
}
|
||||
}
|
||||
done();
|
||||
});
|
||||
it("should correctly deserialize a pageable type with nextLink", function (done) {
|
||||
let client = new testClient_1.TestClient("http://localhost:9090");
|
||||
let mapper = mappers_1.Mappers.ProductListResultNextLink;
|
||||
let responseBody = {
|
||||
value: [
|
||||
{
|
||||
id: 101,
|
||||
name: "TestProduct",
|
||||
properties: {
|
||||
provisioningState: "Succeeded"
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 104,
|
||||
name: "TestProduct1",
|
||||
properties: {
|
||||
provisioningState: "Failed"
|
||||
}
|
||||
}
|
||||
],
|
||||
nextLink: "https://helloworld.com"
|
||||
};
|
||||
let deserializedProduct = client.serializer.deserialize(mapper, responseBody, "responseBody");
|
||||
(Array.isArray(deserializedProduct)).should.be.true;
|
||||
deserializedProduct.length.should.equal(2);
|
||||
deserializedProduct.nextLink.should.equal("https://helloworld.com");
|
||||
for (let i = 0; i < deserializedProduct.length; i++) {
|
||||
if (i === 0) {
|
||||
deserializedProduct[i].id.should.equal(101);
|
||||
deserializedProduct[i].name.should.equal("TestProduct");
|
||||
deserializedProduct[i].provisioningState.should.equal("Succeeded");
|
||||
}
|
||||
else if (i === 1) {
|
||||
deserializedProduct[i].id.should.equal(104);
|
||||
deserializedProduct[i].name.should.equal("TestProduct1");
|
||||
deserializedProduct[i].provisioningState.should.equal("Failed");
|
||||
}
|
||||
}
|
||||
done();
|
||||
});
|
||||
it("should correctly deserialize object version of polymorphic discriminator", function (done) {
|
||||
let client = new testClient_1.TestClient("http://localhost:9090");
|
||||
let mapper = mappers_1.Mappers.Fish;
|
||||
let responseBody = {
|
||||
"fish.type": "sawshark",
|
||||
"age": 22,
|
||||
"birthday": new Date("2012-01-05T01:00:00Z").toISOString(),
|
||||
"species": "king",
|
||||
"length": 1.0,
|
||||
"picture": new Buffer([255, 255, 255, 255, 254]).toString(),
|
||||
"siblings": [
|
||||
{
|
||||
"fish.type": "shark",
|
||||
"age": 6,
|
||||
"birthday": new Date("2012-01-05T01:00:00Z"),
|
||||
"length": 20.0,
|
||||
"species": "predator"
|
||||
},
|
||||
{
|
||||
"fish.type": "sawshark",
|
||||
"age": 105,
|
||||
"birthday": new Date("1900-01-05T01:00:00Z").toISOString(),
|
||||
"length": 10.0,
|
||||
"picture": new Buffer([255, 255, 255, 255, 254]).toString(),
|
||||
"species": "dangerous"
|
||||
}
|
||||
]
|
||||
};
|
||||
let deserializedSawshark = client.serializer.deserialize(mapper, responseBody, "responseBody");
|
||||
deserializedSawshark.age.should.equal(22);
|
||||
deserializedSawshark.fishtype.should.equal("sawshark");
|
||||
deserializedSawshark.siblings.length.should.equal(2);
|
||||
deserializedSawshark.siblings[0].fishtype.should.equal("shark");
|
||||
deserializedSawshark.siblings[0].age.should.equal(6);
|
||||
deserializedSawshark.siblings[0].birthday.toISOString().should.equal("2012-01-05T01:00:00.000Z");
|
||||
deserializedSawshark.siblings[1].fishtype.should.equal("sawshark");
|
||||
deserializedSawshark.siblings[1].age.should.equal(105);
|
||||
deserializedSawshark.siblings[1].birthday.toISOString().should.equal("1900-01-05T01:00:00.000Z");
|
||||
done();
|
||||
});
|
||||
it("should correctly deserialize string version of polymorphic discriminator", function (done) {
|
||||
let client = new testClient_1.TestClient("http://localhost:9090");
|
||||
let mapper = mappers_1.Mappers.PetGallery;
|
||||
let petgallery = {
|
||||
"id": 1,
|
||||
"name": "Fav pet gallery",
|
||||
"pets": [
|
||||
{
|
||||
"id": 2,
|
||||
"name": "moti",
|
||||
"food": "buiscuit",
|
||||
"pet.type": "Dog",
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"name": "billa",
|
||||
"color": "red",
|
||||
"pet.type": "Cat",
|
||||
}
|
||||
]
|
||||
};
|
||||
let deserializedPetGallery = client.serializer.deserialize(mapper, petgallery, "result");
|
||||
deserializedPetGallery.id.should.equal(1);
|
||||
deserializedPetGallery.name.should.equal("Fav pet gallery");
|
||||
deserializedPetGallery.pets.length.should.equal(2);
|
||||
deserializedPetGallery.pets[0]["pettype"].should.equal("Dog");
|
||||
deserializedPetGallery.pets[0].id.should.equal(2);
|
||||
deserializedPetGallery.pets[0].name.should.equal("moti");
|
||||
deserializedPetGallery.pets[0].food.should.equal("buiscuit");
|
||||
deserializedPetGallery.pets[1]["pettype"].should.equal("Cat");
|
||||
deserializedPetGallery.pets[1].id.should.equal(3);
|
||||
deserializedPetGallery.pets[1].name.should.equal("billa");
|
||||
deserializedPetGallery.pets[1].color.should.equal("red");
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
//# sourceMappingURL=serializationTests.js.map
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -0,0 +1,65 @@
|
|||
"use strict";
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const assert = require("assert");
|
||||
const webResource_1 = require("../lib/webResource");
|
||||
const msRestUserAgentFilter_1 = require("../lib/filters/msRestUserAgentFilter");
|
||||
const constants_1 = require("../lib/util/constants");
|
||||
const should = require("should");
|
||||
const userAgentHeader = constants_1.Constants.HeaderConstants.USER_AGENT;
|
||||
describe("ms-rest user agent filter", () => {
|
||||
it("should construct user agent header when supplied empty array", (done) => {
|
||||
const userAgentArray = [];
|
||||
const userAgentFilter = new msRestUserAgentFilter_1.MsRestUserAgentFilter(userAgentArray);
|
||||
const resource = new webResource_1.WebResource();
|
||||
resource.headers = {};
|
||||
userAgentFilter.before(resource).then((resource) => {
|
||||
should.ok(resource);
|
||||
resource.headers[userAgentHeader].should.containEql("Node");
|
||||
resource.headers[userAgentHeader].should.containEql("Azure-SDK-For-Node");
|
||||
done();
|
||||
}).catch((err) => { done(err); });
|
||||
});
|
||||
it("should not modify user agent header if already present", (done) => {
|
||||
const genericRuntime = "ms-rest";
|
||||
const azureRuntime = "ms-rest-azure";
|
||||
const azureSDK = "Azure-SDK-For-Node";
|
||||
const userAgentArray = [`${genericRuntime}/v1.0.0`, `${azureRuntime}/v1.0.0`];
|
||||
const userAgentFilter = new msRestUserAgentFilter_1.MsRestUserAgentFilter(userAgentArray);
|
||||
const customUA = "my custom user agent";
|
||||
const resource = new webResource_1.WebResource();
|
||||
resource.headers = {};
|
||||
resource.headers[userAgentHeader] = customUA;
|
||||
userAgentFilter.before(resource).then((resource) => {
|
||||
should.ok(resource);
|
||||
const actualUA = resource.headers[userAgentHeader];
|
||||
actualUA.should.not.containEql("Node");
|
||||
actualUA.should.not.containEql(azureSDK);
|
||||
actualUA.should.not.containEql(azureRuntime);
|
||||
actualUA.should.containEql(customUA);
|
||||
done();
|
||||
}).catch((err) => { done(err); });
|
||||
});
|
||||
it("should insert azure-sdk-for-node at right position", (done) => {
|
||||
const genericRuntime = "ms-rest";
|
||||
const azureRuntime = "ms-rest-azure";
|
||||
const azureSDK = "Azure-SDK-For-Node";
|
||||
const userAgentArray = [`${genericRuntime}/v1.0.0`, `${azureRuntime}/v1.0.0`];
|
||||
const userAgentFilter = new msRestUserAgentFilter_1.MsRestUserAgentFilter(userAgentArray);
|
||||
const resource = new webResource_1.WebResource();
|
||||
resource.headers = {};
|
||||
userAgentFilter.before(resource).then((resource) => {
|
||||
should.ok(resource);
|
||||
const deconstructedUserAgent = resource.headers[userAgentHeader].split(" ");
|
||||
should.ok(deconstructedUserAgent);
|
||||
const indexOfAzureRuntime = deconstructedUserAgent.findIndex((e) => e.startsWith(azureRuntime));
|
||||
assert.notEqual(indexOfAzureRuntime, -1, `did not find ${azureRuntime} in user agent`);
|
||||
const indexOfAzureSDK = deconstructedUserAgent.indexOf(azureSDK);
|
||||
assert.notEqual(indexOfAzureSDK, -1, `did not find ${azureSDK} in user agent`);
|
||||
assert.equal(indexOfAzureSDK, 1 + indexOfAzureRuntime, `${azureSDK} is not in the right place in user agent string`);
|
||||
done();
|
||||
}).catch((err) => { done(err); });
|
||||
});
|
||||
});
|
||||
//# sourceMappingURL=userAgentFilterTests.js.map
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"userAgentFilterTests.js","sourceRoot":"","sources":["../../test/userAgentFilterTests.ts"],"names":[],"mappings":"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"}
|
|
@ -0,0 +1,30 @@
|
|||
var gulp = require("gulp"),
|
||||
tslint = require("gulp-tslint"),
|
||||
tsc = require("gulp-typescript"),
|
||||
sourcemaps = require("gulp-sourcemaps"),
|
||||
runSequence = require("run-sequence"),
|
||||
mocha = require("gulp-mocha");
|
||||
|
||||
gulp.task('default', function () {
|
||||
console.log("run gulp -T to see all available tasks.\n");
|
||||
});
|
||||
|
||||
gulp.task("lint", () =>
|
||||
gulp.src([
|
||||
"lib/**/**.ts",
|
||||
"test/**/**.ts"
|
||||
])
|
||||
.pipe(tslint({
|
||||
formatter: "verbose"
|
||||
}))
|
||||
.pipe(tslint.report())
|
||||
);
|
||||
|
||||
// TODO: Doesn't yet confirm to folder structure
|
||||
gulp.task("build", () =>
|
||||
gulp.src([
|
||||
"lib/**/**.ts"
|
||||
])
|
||||
.pipe(tsc(tsc.createProject("tsconfig.json")))
|
||||
.js.pipe(gulp.dest("dist/lib/"))
|
||||
);
|
|
@ -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 { Constants } from "../util/constants";
|
||||
import { WebResource } from "../webResource";
|
||||
import { ServiceClientCredentials } from "./serviceClientCredentials";
|
||||
const HeaderConstants = Constants.HeaderConstants;
|
||||
const DEFAULT_AUTHORIZATION_SCHEME = "Basic";
|
||||
|
||||
/**
|
||||
* Creates a new BasicAuthenticationCredentials object.
|
||||
*
|
||||
* @constructor
|
||||
* @param {string} userName User name.
|
||||
* @param {string} password Password.
|
||||
* @param {string} [authorizationScheme] The authorization scheme.
|
||||
*/
|
||||
export class BasicAuthenticationCredentials implements ServiceClientCredentials {
|
||||
userName: string;
|
||||
password: string;
|
||||
authorizationScheme: string = DEFAULT_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 {WebResource} The WebResource to be signed.
|
||||
* @returns {Promise<WebResource>} - The signed request object.
|
||||
*/
|
||||
signRequest(webResource: WebResource) {
|
||||
const credentials = `${this.userName}:${this.password}`;
|
||||
const encodedCredentials = `${this.authorizationScheme} ${Buffer.from(credentials).toString("base64")}`;
|
||||
if (!webResource.headers) webResource.headers = {};
|
||||
webResource.headers[HeaderConstants.AUTHORIZATION] = encodedCredentials;
|
||||
return Promise.resolve(webResource);
|
||||
}
|
||||
}
|
|
@ -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 { WebResource } from "../webResource";
|
||||
|
||||
export interface ServiceClientCredentials {
|
||||
/**
|
||||
* Signs a request with the Authentication header.
|
||||
*
|
||||
* @param {WebResource} webResource The WebResource/request to be signed.
|
||||
* @returns {Promise<WebResource>} The signed request object;
|
||||
*/
|
||||
signRequest(webResource: WebResource): Promise<WebResource>;
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
import { Constants } from "../util/constants";
|
||||
import { WebResource } from "../webResource";
|
||||
import { ServiceClientCredentials } from "./serviceClientCredentials";
|
||||
|
||||
const HeaderConstants = Constants.HeaderConstants;
|
||||
const DEFAULT_AUTHORIZATION_SCHEME = "Bearer";
|
||||
|
||||
/**
|
||||
* Creates a new TokenCredentials object.
|
||||
*
|
||||
* @constructor
|
||||
* @param {string} token The token.
|
||||
* @param {string} authorizationScheme The authorization scheme.
|
||||
*/
|
||||
export class TokenCredentials implements ServiceClientCredentials {
|
||||
token: string;
|
||||
authorizationScheme: string = DEFAULT_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 {WebResource} The WebResource to be signed.
|
||||
* @return {Promise<WebResource>} The signed request object.
|
||||
*/
|
||||
signRequest(webResource: WebResource) {
|
||||
if (!webResource.headers) webResource.headers = {};
|
||||
webResource.headers[HeaderConstants.AUTHORIZATION] = `${this.authorizationScheme} ${this.token}`;
|
||||
return Promise.resolve(webResource);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
import { WebResource } from "../webResource";
|
||||
import { HttpOperationResponse } from "../httpOperationResponse";
|
||||
|
||||
export class BaseFilter {
|
||||
|
||||
constructor() { }
|
||||
|
||||
before(request: WebResource): Promise<WebResource> {
|
||||
return Promise.resolve(request);
|
||||
}
|
||||
|
||||
after(response: HttpOperationResponse): Promise<HttpOperationResponse> {
|
||||
return Promise.resolve(response);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,132 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
import { BaseFilter } from "./baseFilter";
|
||||
import * as utils from "../util/utils";
|
||||
import { HttpOperationResponse } from "../httpOperationResponse";
|
||||
|
||||
export interface RetryData {
|
||||
retryCount: number;
|
||||
retryInterval: number;
|
||||
error?: RetryError;
|
||||
}
|
||||
|
||||
export interface RetryError extends Error {
|
||||
message: string;
|
||||
code?: string;
|
||||
innerError?: RetryError;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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 ExponentialRetryPolicyFilter extends BaseFilter {
|
||||
|
||||
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(retryCount?: number, retryInterval?: number, minRetryInterval?: number, maxRetryInterval?: number) {
|
||||
super();
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
shouldRetry(statusCode: number, retryData: RetryData): boolean {
|
||||
if ((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 < this.retryCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the retry data for the next attempt.
|
||||
*
|
||||
* @param {RetryData} retryData The retry data.
|
||||
* @param {object} err The operation"s error, if any.
|
||||
*/
|
||||
updateRetryData(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 = this.retryInterval * 0.8 +
|
||||
Math.floor(Math.random() * (this.retryInterval * 1.2 - this.retryInterval * 0.8));
|
||||
incrementDelta *= boundedRandDelta;
|
||||
|
||||
retryData.retryInterval = Math.min(this.minRetryInterval + incrementDelta, this.maxRetryInterval);
|
||||
|
||||
return retryData;
|
||||
}
|
||||
|
||||
async retry(operationResponse: HttpOperationResponse, retryData?: RetryData, err?: RetryError): Promise<HttpOperationResponse> {
|
||||
const self = this;
|
||||
const response = operationResponse.response;
|
||||
retryData = self.updateRetryData(retryData, err);
|
||||
if (!utils.objectIsNull(response) && self.shouldRetry(response.status, retryData)) {
|
||||
try {
|
||||
await utils.delay(retryData.retryInterval);
|
||||
const res: HttpOperationResponse = await utils.dispatchRequest(operationResponse.request);
|
||||
return self.retry(res, retryData, err);
|
||||
} catch (err) {
|
||||
return self.retry(operationResponse, retryData, err);
|
||||
}
|
||||
} else {
|
||||
if (!utils.objectIsNull(err)) {
|
||||
// If the operation failed in the end, return all errors instead of just the last one
|
||||
err = retryData.error;
|
||||
return Promise.reject(err);
|
||||
}
|
||||
return Promise.resolve(operationResponse);
|
||||
}
|
||||
}
|
||||
|
||||
after(operationResponse: HttpOperationResponse): Promise<HttpOperationResponse> {
|
||||
return this.retry(operationResponse);
|
||||
}
|
||||
}
|
|
@ -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 { BaseFilter } from "./baseFilter";
|
||||
import { HttpOperationResponse } from "../httpOperationResponse";
|
||||
|
||||
export class LogFilter extends BaseFilter {
|
||||
|
||||
logger?: any;
|
||||
|
||||
constructor(logger: any = console.log) {
|
||||
super();
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
after(operationResponse: HttpOperationResponse): Promise<HttpOperationResponse> {
|
||||
const self = this;
|
||||
self.logger(`>> Request: ${JSON.stringify(operationResponse.request, undefined, 2)}`);
|
||||
self.logger(`>> Response status code: ${operationResponse.response.status}`);
|
||||
const responseBody = operationResponse.bodyAsText;
|
||||
self.logger(`>> Body: ${responseBody}`);
|
||||
return Promise.resolve(operationResponse);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
import { BaseFilter } from "./baseFilter";
|
||||
import { WebResource } from "../webResource";
|
||||
import { Constants } from "../util/constants";
|
||||
import * as os from "os";
|
||||
|
||||
const isNode = require("detect-node");
|
||||
const HeaderConstants = Constants.HeaderConstants;
|
||||
|
||||
export class MsRestUserAgentFilter extends BaseFilter {
|
||||
|
||||
userAgentInfo: Array<string>;
|
||||
|
||||
constructor(userAgentInfo: Array<string>) {
|
||||
super();
|
||||
this.userAgentInfo = userAgentInfo;
|
||||
}
|
||||
|
||||
tagRequest(request: WebResource): Promise<WebResource> {
|
||||
if (isNode) {
|
||||
const osInfo = `(${os.arch()}-${os.type()}-${os.release()})`;
|
||||
if (this.userAgentInfo.indexOf(osInfo) === -1) {
|
||||
this.userAgentInfo.unshift(osInfo);
|
||||
}
|
||||
|
||||
const runtimeInfo = `Node/${process.version}`;
|
||||
if (this.userAgentInfo.indexOf(runtimeInfo) === -1) {
|
||||
this.userAgentInfo.unshift(runtimeInfo);
|
||||
}
|
||||
|
||||
const nodeSDKSignature = `Azure-SDK-For-Node`;
|
||||
if (this.userAgentInfo.indexOf(nodeSDKSignature) === -1) {
|
||||
const azureRuntime = `ms-rest-azure`;
|
||||
|
||||
let insertIndex = this.userAgentInfo.indexOf(azureRuntime);
|
||||
// insert after azureRuntime, otherwise, insert last.
|
||||
insertIndex = insertIndex < 0 ? this.userAgentInfo.length : insertIndex + 1;
|
||||
this.userAgentInfo.splice(insertIndex, 0, nodeSDKSignature);
|
||||
}
|
||||
if (!request.headers) request.headers = {};
|
||||
request.headers[HeaderConstants.USER_AGENT] = this.userAgentInfo.join(" ");
|
||||
}
|
||||
return Promise.resolve(request);
|
||||
}
|
||||
|
||||
before(request: WebResource): Promise<WebResource> {
|
||||
const self = this;
|
||||
if (!request.headers) request.headers = {};
|
||||
if (!request.headers[HeaderConstants.USER_AGENT]) {
|
||||
return self.tagRequest(request);
|
||||
} else {
|
||||
return Promise.resolve(request);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
import { BaseFilter } from "./baseFilter";
|
||||
import { HttpOperationResponse } from "../httpOperationResponse";
|
||||
import * as utils from "../util/utils";
|
||||
|
||||
const parse = require("url-parse");
|
||||
|
||||
export class RedirectFilter extends BaseFilter {
|
||||
|
||||
maximumRetries?: number;
|
||||
|
||||
constructor(maximumRetries = 20) {
|
||||
super();
|
||||
this.maximumRetries = maximumRetries;
|
||||
}
|
||||
|
||||
async handleRedirect(operationResponse: HttpOperationResponse, currentRetries: number): Promise<HttpOperationResponse> {
|
||||
const request = operationResponse.request;
|
||||
const response = operationResponse.response;
|
||||
if (response && response.headers && response.headers.get("location") &&
|
||||
(response.status === 300 || response.status === 307 || (response.status === 303 && request.method === "POST")) &&
|
||||
(!this.maximumRetries || currentRetries < this.maximumRetries)) {
|
||||
if (parse(response.headers.get("location")).hostname) {
|
||||
request.url = response.headers.get("location") as string;
|
||||
} else {
|
||||
const urlObject = parse(request.url);
|
||||
urlObject.set("pathname", response.headers.get("location") as string);
|
||||
request.url = urlObject.href;
|
||||
}
|
||||
// POST request with Status code 303 should be converted into a
|
||||
// redirected GET request if the redirect url is present in the location header
|
||||
if (response.status === 303) {
|
||||
request.method = "GET";
|
||||
}
|
||||
let res: HttpOperationResponse;
|
||||
try {
|
||||
res = await utils.dispatchRequest(request);
|
||||
currentRetries++;
|
||||
} catch (err) {
|
||||
return Promise.reject(err);
|
||||
}
|
||||
return this.handleRedirect(res, currentRetries);
|
||||
}
|
||||
return Promise.resolve(operationResponse);
|
||||
}
|
||||
|
||||
after(operationResponse: HttpOperationResponse): Promise<HttpOperationResponse> {
|
||||
return this.handleRedirect(operationResponse, 0);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,180 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
import { BaseFilter } from "./baseFilter";
|
||||
import { HttpOperationResponse } from "../httpOperationResponse";
|
||||
import { WebResource } from "../webResource";
|
||||
import * as utils from "../util/utils";
|
||||
|
||||
let retryTimeout = 30;
|
||||
|
||||
export class RPRegistrationFilter extends BaseFilter {
|
||||
|
||||
constructor(retryTimeout = 30) {
|
||||
super();
|
||||
retryTimeout = retryTimeout;
|
||||
}
|
||||
|
||||
async after(operationResponse: HttpOperationResponse): Promise<HttpOperationResponse> {
|
||||
let rpName, urlPrefix;
|
||||
const options = operationResponse.request;
|
||||
if (operationResponse.response.status === 409) {
|
||||
rpName = this.checkRPNotRegisteredError(operationResponse.bodyAsText as string);
|
||||
}
|
||||
if (rpName) {
|
||||
urlPrefix = this.extractSubscriptionUrl(options.url);
|
||||
let registrationStatus = false;
|
||||
try {
|
||||
registrationStatus = await this.registerRP(urlPrefix, rpName, options);
|
||||
} catch (err) {
|
||||
// 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.
|
||||
}
|
||||
|
||||
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.
|
||||
options.headers["x-ms-client-request-id"] = utils.generateUuid();
|
||||
let finalRes: HttpOperationResponse;
|
||||
try {
|
||||
finalRes = await utils.dispatchRequest(options);
|
||||
} catch (err) {
|
||||
return Promise.reject(err);
|
||||
}
|
||||
return Promise.resolve(finalRes);
|
||||
}
|
||||
}
|
||||
return Promise.resolve(operationResponse);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reuses the headers of the original request and url (if specified).
|
||||
* @param {WebResource} originalRequest The original request
|
||||
* @param {boolean} reuseUrlToo Should the url from the original request be reused as well. Default false.
|
||||
* @returns {object} reqOptions - A new request object with desired headers.
|
||||
*/
|
||||
getRequestEssentials(originalRequest: WebResource, reuseUrlToo = false): any {
|
||||
const reqOptions: any = {
|
||||
headers: {}
|
||||
};
|
||||
if (reuseUrlToo) {
|
||||
reqOptions.url = originalRequest.url;
|
||||
}
|
||||
|
||||
// Copy over the original request headers. This will get us the auth token and other useful stuff from
|
||||
// the original request header. Thus making it easier to make requests from this filter.
|
||||
for (const h in originalRequest.headers) {
|
||||
reqOptions.headers[h] = originalRequest.headers[h];
|
||||
}
|
||||
// We have to change the x-ms-client-request-id otherwise Azure endpoint
|
||||
// will return the initial 409 (cached) response.
|
||||
reqOptions.headers["x-ms-client-request-id"] = utils.generateUuid();
|
||||
|
||||
// Set content-type to application/json
|
||||
reqOptions.headers["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} result The name of the RP if condition is satisfied else undefined.
|
||||
*/
|
||||
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} urlPrefix The url prefix as explained above.
|
||||
*/
|
||||
extractSubscriptionUrl(url: string): string {
|
||||
let result;
|
||||
const matchRes = url.match(/.*\/subscriptions\/[a-f0-9-]+\//ig);
|
||||
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 {string} urlPrefix - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/
|
||||
* @param {string} provider - The provider name to be registered.
|
||||
* @param {object} 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
|
||||
*/
|
||||
async registerRP(urlPrefix: string, provider: string, originalRequest: WebResource): 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 = this.getRequestEssentials(originalRequest);
|
||||
reqOptions.method = "POST";
|
||||
reqOptions.url = postUrl;
|
||||
let res: HttpOperationResponse;
|
||||
try {
|
||||
res = await utils.dispatchRequest(reqOptions);
|
||||
} catch (err) {
|
||||
return Promise.reject(err);
|
||||
}
|
||||
if (res.response.status !== 200) {
|
||||
return Promise.reject(new Error(`Autoregistration of ${provider} failed. Please try registering manually.`));
|
||||
}
|
||||
let statusRes = false;
|
||||
try {
|
||||
statusRes = await this.getRegistrationStatus(getUrl, originalRequest);
|
||||
} catch (err) {
|
||||
return Promise.reject(err);
|
||||
}
|
||||
return Promise.resolve(statusRes);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 {string} url - The request url for polling
|
||||
* @param {object} 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>} promise - True if RP Registration is successful.
|
||||
*/
|
||||
async getRegistrationStatus(url: string, originalRequest: WebResource): Promise<boolean> {
|
||||
const reqOptions: any = this.getRequestEssentials(originalRequest);
|
||||
let res: HttpOperationResponse;
|
||||
let result = false;
|
||||
reqOptions.url = url;
|
||||
reqOptions.method = "GET";
|
||||
try {
|
||||
res = await utils.dispatchRequest(reqOptions);
|
||||
} catch (err) {
|
||||
return Promise.reject(err);
|
||||
}
|
||||
const obj = (res.bodyAsJson as any);
|
||||
if (res.bodyAsJson && obj.registrationState && obj.registrationState === "Registered") {
|
||||
result = true;
|
||||
} else {
|
||||
setTimeout(() => { return this.getRegistrationStatus(url, originalRequest); }, retryTimeout * 1000);
|
||||
}
|
||||
return Promise.resolve(result);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
import { BaseFilter } from "./baseFilter";
|
||||
import { WebResource } from "../webResource";
|
||||
import { ServiceClientCredentials } from "../credentials/serviceClientCredentials";
|
||||
|
||||
export class SigningFilter extends BaseFilter {
|
||||
|
||||
authenticationProvider: ServiceClientCredentials;
|
||||
|
||||
constructor(authenticationProvider: ServiceClientCredentials) {
|
||||
super();
|
||||
this.authenticationProvider = authenticationProvider;
|
||||
}
|
||||
|
||||
before(request: WebResource): Promise<WebResource> {
|
||||
const self = this;
|
||||
return self.authenticationProvider.signRequest(request);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,129 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
import { BaseFilter } from "./baseFilter";
|
||||
import * as utils from "../util/utils";
|
||||
import { HttpOperationResponse } from "../httpOperationResponse";
|
||||
|
||||
export interface RetryData {
|
||||
retryCount: number;
|
||||
retryInterval: number;
|
||||
error?: RetryError;
|
||||
}
|
||||
|
||||
export interface RetryError extends Error {
|
||||
message: string;
|
||||
code?: string;
|
||||
innerError?: RetryError;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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 SystemErrorRetryPolicyFilter extends BaseFilter {
|
||||
|
||||
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(retryCount?: number, retryInterval?: number, minRetryInterval?: number, maxRetryInterval?: number) {
|
||||
super();
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
shouldRetry(retryData: RetryData): boolean {
|
||||
let currentCount;
|
||||
if (!retryData) {
|
||||
throw new Error("retryData for the SystemErrorRetryPolicyFilter cannot be null.");
|
||||
} else {
|
||||
currentCount = (retryData && retryData.retryCount);
|
||||
}
|
||||
return (currentCount < this.retryCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the retry data for the next attempt.
|
||||
*
|
||||
* @param {RetryData} retryData The retry data.
|
||||
* @param {object} err The operation"s error, if any.
|
||||
*/
|
||||
updateRetryData(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 = this.retryInterval * 0.8 +
|
||||
Math.floor(Math.random() * (this.retryInterval * 1.2 - this.retryInterval * 0.8));
|
||||
incrementDelta *= boundedRandDelta;
|
||||
|
||||
retryData.retryInterval = Math.min(this.minRetryInterval + incrementDelta, this.maxRetryInterval);
|
||||
|
||||
return retryData;
|
||||
}
|
||||
|
||||
async retry(operationResponse: HttpOperationResponse, retryData?: RetryData, err?: RetryError): Promise<HttpOperationResponse> {
|
||||
const self = this;
|
||||
retryData = self.updateRetryData(retryData, err);
|
||||
if (err && err.code && self.shouldRetry(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);
|
||||
const res: HttpOperationResponse = await utils.dispatchRequest(operationResponse.request);
|
||||
return self.retry(res, retryData, err);
|
||||
} catch (err) {
|
||||
return self.retry(operationResponse, retryData, err);
|
||||
}
|
||||
} else {
|
||||
if (!utils.objectIsNull(err)) {
|
||||
// If the operation failed in the end, return all errors instead of just the last one
|
||||
err = retryData.error;
|
||||
return Promise.reject(err);
|
||||
}
|
||||
return Promise.resolve(operationResponse);
|
||||
}
|
||||
}
|
||||
|
||||
after(operationResponse: HttpOperationResponse): Promise<HttpOperationResponse> {
|
||||
return this.retry(operationResponse); // See: https://github.com/Microsoft/TypeScript/issues/7426
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
import { WebResource } from "./webResource";
|
||||
|
||||
/**
|
||||
* Wrapper object for http request and response. Deserialized object is stored in
|
||||
* the `body` property.
|
||||
* @class
|
||||
* Initializes a new instance of the HttpOperationResponse class.
|
||||
* @constructor
|
||||
*/
|
||||
export class HttpOperationResponse {
|
||||
/**
|
||||
* The raw request
|
||||
*/
|
||||
request: WebResource;
|
||||
/**
|
||||
* The raw response
|
||||
*/
|
||||
response: Response;
|
||||
/**
|
||||
* The response body as a readable stream
|
||||
*/
|
||||
bodyAsStream: ReadableStream | null;
|
||||
/**
|
||||
* The response body as text (string format)
|
||||
*/
|
||||
bodyAsText: string | null;
|
||||
/**
|
||||
* The response body as parsed JSON
|
||||
*/
|
||||
bodyAsJson: { [key: string]: any } | Array<any> | string | number | boolean | null | void;
|
||||
|
||||
constructor(request: WebResource, response: Response, body: ReadableStream | null) {
|
||||
/**
|
||||
* Reference to the original request object.
|
||||
* [WebResource] object.
|
||||
* @type {object}
|
||||
*/
|
||||
this.request = request;
|
||||
|
||||
/**
|
||||
* Reference to the original response object.
|
||||
* [ServerResponse] object.
|
||||
* @type {object}
|
||||
*/
|
||||
this.response = response;
|
||||
|
||||
/**
|
||||
* The response object.
|
||||
* @type {object}
|
||||
*/
|
||||
this.bodyAsStream = body;
|
||||
this.bodyAsText = null;
|
||||
this.bodyAsJson = null;
|
||||
}
|
||||
}
|
|
@ -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 { WebResource, RequestPrepareOptions, HttpMethods, ParameterValue, RequestOptionsBase } from "./webResource";
|
||||
import { HttpOperationResponse } from "./httpOperationResponse";
|
||||
import { RestError } from "./restError";
|
||||
import { ServiceClient, ServiceClientOptions } from "./serviceClient";
|
||||
import { Constants } from "./util/constants";
|
||||
import { RequestPipeline, RequestFunction } from "./requestPipeline";
|
||||
import { LogFilter } from "./filters/logFilter";
|
||||
import { BaseFilter } from "./filters/baseFilter";
|
||||
import { ExponentialRetryPolicyFilter } from "./filters/exponentialRetryPolicyFilter";
|
||||
import { SystemErrorRetryPolicyFilter } from "./filters/systemErrorRetryPolicyFilter";
|
||||
import { RedirectFilter } from "./filters/redirectFilter";
|
||||
import { SigningFilter } from "./filters/signingFilter";
|
||||
import { MsRestUserAgentFilter } from "./filters/msRestUserAgentFilter";
|
||||
import {
|
||||
BaseMapperType, CompositeMapper, DictionaryMapper, EnumMapper, Mapper,
|
||||
MapperConstraints, MapperType, PolymorphicDiscriminator,
|
||||
SequenceMapper, Serializer, UrlParameterValue, serializeObject
|
||||
} from "./serializer";
|
||||
import {
|
||||
stripRequest, stripResponse, delay,
|
||||
executePromisesSequentially, generateUuid, encodeUri, ServiceCallback,
|
||||
promiseToCallback, promiseToServiceCallback, isValidUuid, dispatchRequest
|
||||
} from "./util/utils";
|
||||
|
||||
// Credentials
|
||||
import { TokenCredentials } from "./credentials/tokenCredentials";
|
||||
import { BasicAuthenticationCredentials } from "./credentials/basicAuthenticationCredentials";
|
||||
import { ServiceClientCredentials } from "./credentials/serviceClientCredentials";
|
||||
import * as isStream from "is-stream";
|
||||
|
||||
export {
|
||||
BaseMapperType, CompositeMapper, DictionaryMapper, EnumMapper, Mapper, MapperConstraints, MapperType,
|
||||
PolymorphicDiscriminator, SequenceMapper, UrlParameterValue, Serializer, serializeObject, TokenCredentials,
|
||||
WebResource, RequestPrepareOptions, HttpMethods, ParameterValue, HttpOperationResponse, ServiceClient, Constants, RequestPipeline,
|
||||
BasicAuthenticationCredentials, ServiceClientCredentials, BaseFilter, LogFilter, ServiceClientOptions, ExponentialRetryPolicyFilter,
|
||||
SystemErrorRetryPolicyFilter, SigningFilter, MsRestUserAgentFilter, stripRequest, stripResponse, delay, executePromisesSequentially,
|
||||
generateUuid, isValidUuid, encodeUri, RestError, RequestOptionsBase, RequestFunction, ServiceCallback, promiseToCallback,
|
||||
promiseToServiceCallback, isStream, dispatchRequest, RedirectFilter
|
||||
};
|
|
@ -0,0 +1,58 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
import { WebResource } from "./webResource";
|
||||
import { HttpOperationResponse } from "./httpOperationResponse";
|
||||
import { BaseFilter } from "./filters/baseFilter";
|
||||
import * as utils from "./util/utils";
|
||||
|
||||
export interface RequestFunction {
|
||||
(webResource: WebResource): Promise<HttpOperationResponse>;
|
||||
}
|
||||
export class RequestPipeline {
|
||||
filters: BaseFilter[];
|
||||
requestOptions: RequestInit;
|
||||
|
||||
constructor(filters?: BaseFilter[], requestOptions?: RequestInit) {
|
||||
this.filters = filters || [];
|
||||
this.requestOptions = requestOptions || {};
|
||||
}
|
||||
|
||||
addFilter(f: BaseFilter): void {
|
||||
this.filters.push(f);
|
||||
return;
|
||||
}
|
||||
|
||||
create(): RequestFunction {
|
||||
const self = this;
|
||||
let pipeline: Array<Function> = [];
|
||||
if (self.filters && self.filters.length) {
|
||||
const beforeFilters: Array<Function> = [];
|
||||
const afterFilters: Array<Function> = [];
|
||||
for (let i = 0; i < self.filters.length; i++) {
|
||||
const filter = self.filters[i];
|
||||
if (filter.before && typeof filter.before === "function") {
|
||||
beforeFilters.push(filter.before.bind(filter));
|
||||
}
|
||||
if (filter.after && typeof filter.after === "function") {
|
||||
afterFilters.push(filter.after.bind(filter));
|
||||
}
|
||||
}// end-of-for-loop
|
||||
// add the request sink
|
||||
beforeFilters.push(self.requestSink.bind(self));
|
||||
pipeline = beforeFilters.concat(afterFilters);
|
||||
} else {
|
||||
pipeline.push(self.requestSink.bind(self));
|
||||
}
|
||||
const requestFun: RequestFunction = (request: WebResource): Promise<HttpOperationResponse> => {
|
||||
if (!request.headers) request.headers = {};
|
||||
return utils.executePromisesSequentially(pipeline, request);
|
||||
};
|
||||
return requestFun;
|
||||
}
|
||||
|
||||
requestSink(options: WebResource): Promise<HttpOperationResponse> {
|
||||
if (this.requestOptions.method) delete this.requestOptions.method;
|
||||
return utils.dispatchRequest(options);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
import { WebResource } from "./webResource";
|
||||
|
||||
export class RestError extends Error {
|
||||
code?: string;
|
||||
statusCode?: number;
|
||||
request?: WebResource;
|
||||
response?: Response;
|
||||
body?: any;
|
||||
constructor(message: string, code?: string, statusCode?: number, request?: WebResource, response?: Response, body?: any) {
|
||||
super(message);
|
||||
this.code = code;
|
||||
this.statusCode = statusCode;
|
||||
this.request = request;
|
||||
this.response = response;
|
||||
this.body = body;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,759 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
import * as utils from "./util/utils";
|
||||
import { duration, isDuration } from "moment";
|
||||
const isBuffer = require("is-buffer");
|
||||
import * as isStream from "is-stream";
|
||||
|
||||
export class Serializer {
|
||||
modelMappers?: { [key: string]: any };
|
||||
|
||||
constructor(mappers?: { [key: string]: any }) {
|
||||
this.modelMappers = mappers;
|
||||
}
|
||||
|
||||
validateConstraints(mapper: Mapper, value: any, objectName: string): void {
|
||||
if (mapper.constraints && (value !== null || value !== undefined)) {
|
||||
Object.keys(mapper.constraints).forEach((constraintType) => {
|
||||
if (constraintType.match(/^ExclusiveMaximum$/ig) !== null) {
|
||||
if (value >= ((mapper.constraints as MapperConstraints).ExclusiveMaximum as number)) {
|
||||
throw new Error(`"${objectName}" with value "${value}" should satify the constraint "ExclusiveMaximum": ${((mapper.constraints as MapperConstraints).ExclusiveMaximum as number)}.`);
|
||||
}
|
||||
} else if (constraintType.match(/^ExclusiveMinimum$/ig) !== null) {
|
||||
if (value <= ((mapper.constraints as MapperConstraints).ExclusiveMinimum as number)) {
|
||||
throw new Error(`${objectName} " with value "${value} " should satify the constraint "ExclusiveMinimum": ${((mapper.constraints as MapperConstraints).ExclusiveMinimum as number)}.`);
|
||||
}
|
||||
} else if (constraintType.match(/^InclusiveMaximum$/ig) !== null) {
|
||||
if (value > ((mapper.constraints as MapperConstraints).InclusiveMaximum as number)) {
|
||||
throw new Error(`${objectName}" with value "${value}" should satify the constraint "InclusiveMaximum": ${((mapper.constraints as MapperConstraints).InclusiveMaximum as number)}.`);
|
||||
}
|
||||
} else if (constraintType.match(/^InclusiveMinimum$/ig) !== null) {
|
||||
if (value < ((mapper.constraints as MapperConstraints).InclusiveMinimum as number)) {
|
||||
throw new Error(`${objectName}" with value "${value}" should satify the constraint "InclusiveMinimum": ${((mapper.constraints as MapperConstraints).InclusiveMinimum as number)}.`);
|
||||
}
|
||||
} else if (constraintType.match(/^MaxItems$/ig) !== null) {
|
||||
if (value.length > ((mapper.constraints as MapperConstraints).MaxItems as number)) {
|
||||
throw new Error(`${objectName}" with value "${value}" should satify the constraint "MaxItems": ${((mapper.constraints as MapperConstraints).MaxItems as number)}.`);
|
||||
}
|
||||
} else if (constraintType.match(/^MaxLength$/ig) !== null) {
|
||||
if (value.length > ((mapper.constraints as MapperConstraints).MaxLength as number)) {
|
||||
throw new Error(`${objectName}" with value "${value}" should satify the constraint "MaxLength": ${((mapper.constraints as MapperConstraints).MaxLength as number)}.`);
|
||||
}
|
||||
} else if (constraintType.match(/^MinItems$/ig) !== null) {
|
||||
if (value.length < ((mapper.constraints as MapperConstraints).MinItems as number)) {
|
||||
throw new Error(`${objectName}" with value "${value}" should satify the constraint "MinItems": ${((mapper.constraints as MapperConstraints).MinItems as number)}.`);
|
||||
}
|
||||
} else if (constraintType.match(/^MinLength$/ig) !== null) {
|
||||
if (value.length < ((mapper.constraints as MapperConstraints).MinLength as number)) {
|
||||
throw new Error(`${objectName}" with value "${value}" should satify the constraint "MinLength": ${((mapper.constraints as MapperConstraints).MinLength as number)}.`);
|
||||
}
|
||||
} else if (constraintType.match(/^MultipleOf$/ig) !== null) {
|
||||
if (value.length % ((mapper.constraints as MapperConstraints).MultipleOf as number) !== 0) {
|
||||
throw new Error(`${objectName}" with value "${value}" should satify the constraint "MultipleOf": ${((mapper.constraints as MapperConstraints).MultipleOf as number)}.`);
|
||||
}
|
||||
} else if (constraintType.match(/^Pattern$/ig) !== null) {
|
||||
if (value.match(((mapper.constraints as MapperConstraints).Pattern as string).split("/").join("\/")) === null) {
|
||||
throw new Error(`${objectName}" with value "${value}" should satify the constraint "Pattern": ${((mapper.constraints as MapperConstraints).Pattern as string)}.`);
|
||||
}
|
||||
} else if (constraintType.match(/^UniqueItems/ig) !== null) {
|
||||
if (((mapper.constraints as MapperConstraints).UniqueItems as boolean)) {
|
||||
if (value.length !== value.filter((item: any, i: number, ar: Array<any>) => { { return ar.indexOf(item) === i; } }).length) {
|
||||
throw new Error(`${objectName}" with value "${value}" should satify the constraint "UniqueItems": ${((mapper.constraints as MapperConstraints).UniqueItems as boolean)}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private trimEnd(str: string, ch: string) {
|
||||
let len = str.length;
|
||||
while ((len - 1) >= 0 && str[len - 1] === ch) {
|
||||
--len;
|
||||
}
|
||||
return str.substr(0, len);
|
||||
}
|
||||
|
||||
private bufferToBase64Url(buffer: any): string | undefined {
|
||||
if (!buffer) {
|
||||
return undefined;
|
||||
}
|
||||
if (!isBuffer(buffer)) {
|
||||
throw new Error(`Please provide an input of type Buffer for converting to Base64Url.`);
|
||||
}
|
||||
// Buffer to Base64.
|
||||
const str = buffer.toString("base64");
|
||||
// Base64 to Base64Url.
|
||||
return this.trimEnd(str, "=").replace(/\+/g, "-").replace(/\//g, "_");
|
||||
}
|
||||
|
||||
private base64UrlToBuffer(str: string): any {
|
||||
if (!str) {
|
||||
return undefined;
|
||||
}
|
||||
if (str && typeof str.valueOf() !== "string") {
|
||||
throw new Error("Please provide an input of type string for converting to Buffer");
|
||||
}
|
||||
// Base64Url to Base64.
|
||||
str = str.replace(/\-/g, "+").replace(/\_/g, "/");
|
||||
// Base64 to Buffer.
|
||||
return Buffer.from(str, "base64");
|
||||
}
|
||||
|
||||
private splitSerializeName(prop: string): Array<string> {
|
||||
const classes: Array<string> = [];
|
||||
let partialclass = "";
|
||||
const subwords = prop.split(".");
|
||||
|
||||
subwords.forEach((item) => {
|
||||
if (item.charAt(item.length - 1) === "\\") {
|
||||
partialclass += item.substr(0, item.length - 1) + ".";
|
||||
} else {
|
||||
partialclass += item;
|
||||
classes.push(partialclass);
|
||||
partialclass = "";
|
||||
}
|
||||
});
|
||||
|
||||
return classes;
|
||||
}
|
||||
|
||||
private dateToUnixTime(d: string | Date): number | undefined {
|
||||
if (!d) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (typeof d.valueOf() === "string") {
|
||||
d = new Date(d as string);
|
||||
}
|
||||
return Math.floor((d as Date).getTime() / 1000);
|
||||
}
|
||||
|
||||
private unixTimeToDate(n: number): Date | undefined {
|
||||
if (!n) {
|
||||
return undefined;
|
||||
}
|
||||
return new Date(n * 1000);
|
||||
}
|
||||
|
||||
private serializeBasicTypes(typeName: string, objectName: string, value: any): any {
|
||||
if (value !== null && value !== undefined) {
|
||||
if (typeName.match(/^Number$/ig) !== null) {
|
||||
if (typeof value !== "number") {
|
||||
throw new Error(`${objectName} with value ${value} must be of type number.`);
|
||||
}
|
||||
} else if (typeName.match(/^String$/ig) !== null) {
|
||||
if (typeof value.valueOf() !== "string") {
|
||||
throw new Error(`${objectName} with value "${value}" must be of type string.`);
|
||||
}
|
||||
} else if (typeName.match(/^Uuid$/ig) !== null) {
|
||||
if (!(typeof value.valueOf() === "string" && utils.isValidUuid(value))) {
|
||||
throw new Error(`${objectName} with value "${value}" must be of type string and a valid uuid.`);
|
||||
}
|
||||
} else if (typeName.match(/^Boolean$/ig) !== null) {
|
||||
if (typeof value !== "boolean") {
|
||||
throw new Error(`${objectName} with value ${value} must be of type boolean.`);
|
||||
}
|
||||
} else if (typeName.match(/^Object$/ig) !== null) {
|
||||
if (typeof value !== "object") {
|
||||
throw new Error(`${objectName} must be of type object.`);
|
||||
}
|
||||
} else if (typeName.match(/^Stream$/ig) !== null) {
|
||||
if (!isStream(value)) {
|
||||
throw new Error(`${objectName} must be of type stream.`);
|
||||
}
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
private serializeEnumType(objectName: string, allowedValues: Array<any>, value: any): any {
|
||||
if (!allowedValues) {
|
||||
throw new Error(`Please provide a set of allowedValues to validate ${objectName} as an Enum Type.`);
|
||||
}
|
||||
const isPresent = allowedValues.some((item) => {
|
||||
if (typeof item.valueOf() === "string") {
|
||||
return item.toLowerCase() === value.toLowerCase();
|
||||
}
|
||||
return item === value;
|
||||
});
|
||||
if (!isPresent) {
|
||||
throw new Error(`${value} is not a valid value for ${objectName}. The valid values are: ${JSON.stringify(allowedValues)}.`);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
private serializeBufferType(objectName: string, value: any): any {
|
||||
if (value !== null && value !== undefined) {
|
||||
if (!isBuffer(value)) {
|
||||
throw new Error(`${objectName} must be of type Buffer.`);
|
||||
}
|
||||
value = value.toString("base64");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
private serializeBase64UrlType(objectName: string, value: any): any {
|
||||
if (value !== null && value !== undefined) {
|
||||
if (!isBuffer(value)) {
|
||||
throw new Error(`${objectName} must be of type Buffer.`);
|
||||
}
|
||||
value = this.bufferToBase64Url(value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
private serializeDateTypes(typeName: string, value: any, objectName: string) {
|
||||
if (value !== null && value !== undefined) {
|
||||
if (typeName.match(/^Date$/ig) !== null) {
|
||||
if (!(value instanceof Date ||
|
||||
(typeof value.valueOf() === "string" && !isNaN(Date.parse(value))))) {
|
||||
throw new Error(`${objectName} must be an instanceof Date or a string in ISO8601 format.`);
|
||||
}
|
||||
value = (value instanceof Date) ? value.toISOString().substring(0, 10) : new Date(value).toISOString().substring(0, 10);
|
||||
} else if (typeName.match(/^DateTime$/ig) !== null) {
|
||||
if (!(value instanceof Date ||
|
||||
(typeof value.valueOf() === "string" && !isNaN(Date.parse(value))))) {
|
||||
throw new Error(`${objectName} must be an instanceof Date or a string in ISO8601 format.`);
|
||||
}
|
||||
value = (value instanceof Date) ? value.toISOString() : new Date(value).toISOString();
|
||||
} else if (typeName.match(/^DateTimeRfc1123$/ig) !== null) {
|
||||
if (!(value instanceof Date ||
|
||||
(typeof value.valueOf() === "string" && !isNaN(Date.parse(value))))) {
|
||||
throw new Error(`${objectName} must be an instanceof Date or a string in RFC-1123 format.`);
|
||||
}
|
||||
value = (value instanceof Date) ? value.toUTCString() : new Date(value).toUTCString();
|
||||
} else if (typeName.match(/^UnixTime$/ig) !== null) {
|
||||
if (!(value instanceof Date ||
|
||||
(typeof value.valueOf() === "string" && !isNaN(Date.parse(value))))) {
|
||||
throw new Error(`${objectName} must be an instanceof Date or a string in RFC-1123/ISO8601 format ` +
|
||||
`for it to be serialized in UnixTime/Epoch format.`);
|
||||
}
|
||||
value = this.dateToUnixTime(value);
|
||||
} else if (typeName.match(/^TimeSpan$/ig) !== null) {
|
||||
if (!isDuration(value)) {
|
||||
throw new Error(`${objectName} must be a TimeSpan/Duration.`);
|
||||
}
|
||||
value = value.toISOString();
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
private serializeSequenceType(mapper: SequenceMapper, object: any, objectName: string) {
|
||||
|
||||
if (!Array.isArray(object)) {
|
||||
throw new Error(`${objectName} must be of type Array.`);
|
||||
}
|
||||
if (!mapper.type.element || typeof mapper.type.element !== "object") {
|
||||
throw new Error(`element" metadata for an Array must be defined in the ` +
|
||||
`mapper and it must of type "object" in ${objectName}.`);
|
||||
}
|
||||
const tempArray = [];
|
||||
for (let i = 0; i < object.length; i++) {
|
||||
tempArray[i] = this.serialize(mapper.type.element, object[i], objectName);
|
||||
}
|
||||
return tempArray;
|
||||
}
|
||||
|
||||
private serializeDictionaryType(mapper: DictionaryMapper, object: any, objectName: string) {
|
||||
|
||||
if (typeof object !== "object") {
|
||||
throw new Error(`${objectName} must be of type object.`);
|
||||
}
|
||||
if (!mapper.type.value || typeof mapper.type.value !== "object") {
|
||||
throw new Error(`"value" metadata for a Dictionary must be defined in the ` +
|
||||
`mapper and it must of type "object" in ${objectName}.`);
|
||||
}
|
||||
const tempDictionary: { [key: string]: any } = {};
|
||||
for (const key in object) {
|
||||
if (object.hasOwnProperty(key)) {
|
||||
tempDictionary[key] = this.serialize(mapper.type.value, object[key], objectName);
|
||||
}
|
||||
}
|
||||
return tempDictionary;
|
||||
}
|
||||
|
||||
private serializeCompositeType(mapper: CompositeMapper, object: any, objectName: string) {
|
||||
// check for polymorphic discriminator
|
||||
if (mapper.type.polymorphicDiscriminator) {
|
||||
mapper = this.getPolymorphicMapper(mapper, object, objectName, "serialize");
|
||||
}
|
||||
|
||||
const payload: any = {};
|
||||
let modelMapper: CompositeMapper = {
|
||||
required: false,
|
||||
serializedName: "serializedName",
|
||||
type: {
|
||||
name: "Composite",
|
||||
className: "className",
|
||||
modelProperties: {}
|
||||
}
|
||||
};
|
||||
if (object !== null && object !== undefined) {
|
||||
let modelProps = mapper.type.modelProperties;
|
||||
if (!modelProps) {
|
||||
if (!mapper.type.className) {
|
||||
throw new Error(`Class name for model "${objectName}" is not provided in the mapper "${JSON.stringify(mapper, undefined, 2)}".`);
|
||||
}
|
||||
// get the mapper if modelProperties of the CompositeType is not present and
|
||||
// then get the modelProperties from it.
|
||||
modelMapper = (this.modelMappers as { [key: string]: any })[mapper.type.className];
|
||||
if (!modelMapper) {
|
||||
throw new Error(`mapper() cannot be null or undefined for model "${mapper.type.className}".`);
|
||||
}
|
||||
modelProps = modelMapper.type.modelProperties;
|
||||
if (!modelProps) {
|
||||
throw new Error(`modelProperties cannot be null or undefined in the ` +
|
||||
`mapper "${JSON.stringify(modelMapper)}" of type "${mapper.type.className}" for object "${objectName}".`);
|
||||
}
|
||||
}
|
||||
|
||||
for (const key in modelProps) {
|
||||
if (modelProps.hasOwnProperty(key)) {
|
||||
const paths = this.splitSerializeName(modelProps[key].serializedName);
|
||||
const propName = paths.pop();
|
||||
|
||||
let parentObject: any = payload;
|
||||
paths.forEach((pathName: string) => {
|
||||
const childObject = parentObject[pathName];
|
||||
if ((childObject === null || childObject === undefined) && (object[key] !== null && object[key] !== undefined)) {
|
||||
parentObject[pathName] = {};
|
||||
}
|
||||
parentObject = parentObject[pathName];
|
||||
});
|
||||
|
||||
// make sure required properties of the CompositeType are present
|
||||
if (modelProps[key].required && !modelProps[key].isConstant) {
|
||||
if (object[key] === null || object[key] === undefined) {
|
||||
throw new Error(`${key}" cannot be null or undefined in "${objectName}".`);
|
||||
}
|
||||
}
|
||||
// make sure that readOnly properties are not sent on the wire
|
||||
if (modelProps[key].readOnly) {
|
||||
continue;
|
||||
}
|
||||
// serialize the property if it is present in the provided object instance
|
||||
if (((parentObject !== null && parentObject !== undefined) && (modelProps[key].defaultValue !== null && modelProps[key].defaultValue !== undefined)) ||
|
||||
(object[key] !== null && object[key] !== undefined)) {
|
||||
let propertyObjectName = objectName;
|
||||
if (modelProps[key].serializedName !== "") propertyObjectName = objectName + "." + modelProps[key].serializedName;
|
||||
const propertyMapper = modelProps[key];
|
||||
const serializedValue = this.serialize(propertyMapper, object[key], propertyObjectName);
|
||||
if (propName !== null && propName !== undefined) parentObject[propName] = serializedValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
return payload;
|
||||
}
|
||||
return object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize the given object based on its metadata defined in the mapper
|
||||
*
|
||||
* @param {Mapper} mapper The mapper which defines the metadata of the serializable object
|
||||
*
|
||||
* @param {object|string|Array|number|boolean|Date|stream} object A valid Javascript object to be serialized
|
||||
*
|
||||
* @param {string} objectName Name of the serialized object
|
||||
*
|
||||
* @returns {object|string|Array|number|boolean|Date|stream} A valid serialized Javascript object
|
||||
*/
|
||||
serialize(mapper: Mapper, object: any, objectName: string): any {
|
||||
let payload: any = {};
|
||||
const mapperType = mapper.type.name as string;
|
||||
if (!objectName) objectName = mapper.serializedName;
|
||||
if (mapperType.match(/^Sequence$/ig) !== null) payload = [];
|
||||
// Throw if required and object is null or undefined
|
||||
if (mapper.required && (object === null || object === undefined) && !mapper.isConstant) {
|
||||
throw new Error(`${objectName} cannot be null or undefined.`);
|
||||
}
|
||||
// Set Defaults
|
||||
if ((mapper.defaultValue !== null && mapper.defaultValue !== undefined) &&
|
||||
(object === null || object === undefined)) {
|
||||
object = mapper.defaultValue;
|
||||
}
|
||||
if (mapper.isConstant) object = mapper.defaultValue;
|
||||
// Validate Constraints if any
|
||||
this.validateConstraints(mapper, object, objectName);
|
||||
if (mapperType.match(/^(Number|String|Boolean|Object|Stream|Uuid)$/ig) !== null) {
|
||||
payload = this.serializeBasicTypes(mapperType, objectName, object);
|
||||
} else if (mapperType.match(/^Enum$/ig) !== null) {
|
||||
const enumMapper: EnumMapper = mapper as EnumMapper;
|
||||
payload = this.serializeEnumType(objectName, enumMapper.type.allowedValues, object);
|
||||
} else if (mapperType.match(/^(Date|DateTime|TimeSpan|DateTimeRfc1123|UnixTime)$/ig) !== null) {
|
||||
payload = this.serializeDateTypes(mapperType, object, objectName);
|
||||
} else if (mapperType.match(/^ByteArray$/ig) !== null) {
|
||||
payload = this.serializeBufferType(objectName, object);
|
||||
} else if (mapperType.match(/^Base64Url$/ig) !== null) {
|
||||
payload = this.serializeBase64UrlType(objectName, object);
|
||||
} else if (mapperType.match(/^Sequence$/ig) !== null) {
|
||||
payload = this.serializeSequenceType(mapper as SequenceMapper, object, objectName);
|
||||
} else if (mapperType.match(/^Dictionary$/ig) !== null) {
|
||||
payload = this.serializeDictionaryType(mapper as DictionaryMapper, object, objectName);
|
||||
} else if (mapperType.match(/^Composite$/ig) !== null) {
|
||||
payload = this.serializeCompositeType(mapper as CompositeMapper, object, objectName);
|
||||
}
|
||||
return payload;
|
||||
}
|
||||
|
||||
private deserializeCompositeType(mapper: CompositeMapper, responseBody: any, objectName: string): any {
|
||||
/*jshint validthis: true */
|
||||
// check for polymorphic discriminator
|
||||
if (mapper.type.polymorphicDiscriminator) {
|
||||
mapper = this.getPolymorphicMapper(mapper, responseBody, objectName, "deserialize");
|
||||
}
|
||||
|
||||
let instance: { [key: string]: any } = {};
|
||||
let modelMapper: Mapper = {
|
||||
required: false,
|
||||
serializedName: "serializedName",
|
||||
type: {
|
||||
name: "Composite"
|
||||
}
|
||||
};
|
||||
if (responseBody !== null && responseBody !== undefined) {
|
||||
let modelProps = mapper.type.modelProperties;
|
||||
if (!modelProps) {
|
||||
if (!mapper.type.className) {
|
||||
throw new Error(`Class name for model "${objectName}" is not provided in the mapper "${JSON.stringify(mapper)}"`);
|
||||
}
|
||||
// get the mapper if modelProperties of the CompositeType is not present and
|
||||
// then get the modelProperties from it.
|
||||
modelMapper = (this.modelMappers as { [key: string]: any })[mapper.type.className];
|
||||
if (!modelMapper) {
|
||||
throw new Error(`mapper() cannot be null or undefined for model "${mapper.type.className}"`);
|
||||
}
|
||||
modelProps = (modelMapper as CompositeMapper).type.modelProperties;
|
||||
if (!modelProps) {
|
||||
throw new Error(`modelProperties cannot be null or undefined in the ` +
|
||||
`mapper "${JSON.stringify(modelMapper)}" of type "${mapper.type.className}" for responseBody "${objectName}".`);
|
||||
}
|
||||
}
|
||||
|
||||
for (const key in modelProps) {
|
||||
if (modelProps.hasOwnProperty(key)) {
|
||||
|
||||
const jpath = ["responseBody"];
|
||||
const paths = this.splitSerializeName(modelProps[key].serializedName);
|
||||
paths.forEach((item) => {
|
||||
jpath.push(`["${item}"]`);
|
||||
});
|
||||
// deserialize the property if it is present in the provided responseBody instance
|
||||
let propertyInstance;
|
||||
try {
|
||||
/*jslint evil: true */
|
||||
propertyInstance = eval(jpath.join(""));
|
||||
} catch (err) {
|
||||
continue;
|
||||
}
|
||||
let propertyObjectName = objectName;
|
||||
if (modelProps[key].serializedName !== "") propertyObjectName = objectName + "." + modelProps[key].serializedName;
|
||||
const propertyMapper = modelProps[key];
|
||||
let serializedValue;
|
||||
// paging
|
||||
if (Array.isArray(responseBody[key]) && modelProps[key].serializedName === "") {
|
||||
propertyInstance = responseBody[key];
|
||||
instance = this.deserialize(propertyMapper, propertyInstance, propertyObjectName);
|
||||
} else if (propertyInstance !== null && propertyInstance !== undefined) {
|
||||
serializedValue = this.deserialize(propertyMapper, propertyInstance, propertyObjectName);
|
||||
instance[key] = serializedValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
return responseBody;
|
||||
}
|
||||
|
||||
private deserializeDictionaryType(mapper: DictionaryMapper, responseBody: any, objectName: string): any {
|
||||
/*jshint validthis: true */
|
||||
if (!mapper.type.value || typeof mapper.type.value !== "object") {
|
||||
throw new Error(`"value" metadata for a Dictionary must be defined in the ` +
|
||||
`mapper and it must of type "object" in ${objectName}`);
|
||||
}
|
||||
if (responseBody) {
|
||||
const tempDictionary: { [key: string]: any } = {};
|
||||
for (const key in responseBody) {
|
||||
if (responseBody.hasOwnProperty(key)) {
|
||||
tempDictionary[key] = this.deserialize(mapper.type.value, responseBody[key], objectName);
|
||||
}
|
||||
}
|
||||
return tempDictionary;
|
||||
}
|
||||
return responseBody;
|
||||
}
|
||||
|
||||
private deserializeSequenceType(mapper: SequenceMapper, responseBody: any, objectName: string): any {
|
||||
/*jshint validthis: true */
|
||||
if (!mapper.type.element || typeof mapper.type.element !== "object") {
|
||||
throw new Error(`element" metadata for an Array must be defined in the ` +
|
||||
`mapper and it must of type "object" in ${objectName}`);
|
||||
}
|
||||
if (responseBody) {
|
||||
const tempArray = [];
|
||||
for (let i = 0; i < responseBody.length; i++) {
|
||||
tempArray[i] = this.deserialize(mapper.type.element, responseBody[i], objectName);
|
||||
}
|
||||
return tempArray;
|
||||
}
|
||||
return responseBody;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserialize the given object based on its metadata defined in the mapper
|
||||
*
|
||||
* @param {object} mapper The mapper which defines the metadata of the serializable object
|
||||
*
|
||||
* @param {object|string|Array|number|boolean|Date|stream} responseBody A valid Javascript entity to be deserialized
|
||||
*
|
||||
* @param {string} objectName Name of the deserialized object
|
||||
*
|
||||
* @returns {object|string|Array|number|boolean|Date|stream} A valid deserialized Javascript object
|
||||
*/
|
||||
deserialize(mapper: Mapper, responseBody: any, objectName: string): any {
|
||||
if (responseBody === null || responseBody === undefined) return responseBody;
|
||||
let payload: any;
|
||||
const mapperType = mapper.type.name;
|
||||
if (!objectName) objectName = mapper.serializedName;
|
||||
if (mapperType.match(/^Sequence$/ig) !== null) payload = [];
|
||||
|
||||
if (mapperType.match(/^(Number|String|Boolean|Enum|Object|Stream|Uuid)$/ig) !== null) {
|
||||
payload = responseBody;
|
||||
} else if (mapperType.match(/^(Date|DateTime|DateTimeRfc1123)$/ig) !== null) {
|
||||
payload = new Date(responseBody);
|
||||
} else if (mapperType.match(/^TimeSpan$/ig) !== null) {
|
||||
payload = duration(responseBody);
|
||||
} else if (mapperType.match(/^UnixTime$/ig) !== null) {
|
||||
payload = this.unixTimeToDate(responseBody);
|
||||
} else if (mapperType.match(/^ByteArray$/ig) !== null) {
|
||||
payload = Buffer.from(responseBody, "base64");
|
||||
} else if (mapperType.match(/^Base64Url$/ig) !== null) {
|
||||
payload = this.base64UrlToBuffer(responseBody);
|
||||
} else if (mapperType.match(/^Sequence$/ig) !== null) {
|
||||
payload = this.deserializeSequenceType(mapper as SequenceMapper, responseBody, objectName);
|
||||
} else if (mapperType.match(/^Dictionary$/ig) !== null) {
|
||||
payload = this.deserializeDictionaryType(mapper as DictionaryMapper, responseBody, objectName);
|
||||
} else if (mapperType.match(/^Composite$/ig) !== null) {
|
||||
payload = this.deserializeCompositeType(mapper as CompositeMapper, responseBody, objectName);
|
||||
}
|
||||
|
||||
if (mapper.isConstant) payload = mapper.defaultValue;
|
||||
|
||||
return payload;
|
||||
}
|
||||
|
||||
private getPolymorphicMapper(mapper: CompositeMapper, object: any, objectName: string, mode: string): CompositeMapper {
|
||||
|
||||
// check for polymorphic discriminator
|
||||
// Until version 1.15.1, "polymorphicDiscriminator" in the mapper was a string. This method was not effective when the
|
||||
// polymorphicDiscriminator property had a dot in it"s name. So we have comeup with a desgin where polymorphicDiscriminator
|
||||
// will be an object that contains the clientName (normalized property name, ex: "odatatype") and
|
||||
// the serializedName (ex: "odata.type") (We do not escape the dots with double backslash in this case as it is not required)
|
||||
// Thus when serializing, the user will give us an object which will contain the normalizedProperty hence we will lookup
|
||||
// the clientName of the polmorphicDiscriminator in the mapper and during deserialization from the responseBody we will
|
||||
// lookup the serializedName of the polmorphicDiscriminator in the mapper. This will help us in selecting the correct mapper
|
||||
// for the model that needs to be serializes or deserialized.
|
||||
// We need this routing for backwards compatibility. This will absorb the breaking change in the mapper and allow new versions
|
||||
// of the runtime to work seamlessly with older version (>= 0.17.0-Nightly20161008) of Autorest generated node.js clients.
|
||||
if (mapper.type.polymorphicDiscriminator) {
|
||||
if (typeof mapper.type.polymorphicDiscriminator.valueOf() === "string") {
|
||||
return this.getPolymorphicMapperStringVersion(mapper, object, objectName);
|
||||
} else if (mapper.type.polymorphicDiscriminator instanceof Object) {
|
||||
return this.getPolymorphicMapperObjectVersion(mapper, object, objectName, mode);
|
||||
} else {
|
||||
throw new Error(`The polymorphicDiscriminator for "${objectName}" is neither a string nor an object.`);
|
||||
}
|
||||
}
|
||||
return mapper;
|
||||
}
|
||||
|
||||
// processes new version of the polymorphicDiscriminator in the mapper.
|
||||
private getPolymorphicMapperObjectVersion(mapper: CompositeMapper, object: any, objectName: string, mode: string): CompositeMapper {
|
||||
|
||||
// check for polymorphic discriminator
|
||||
let polymorphicPropertyName = "";
|
||||
if (mode === "serialize") {
|
||||
polymorphicPropertyName = "clientName";
|
||||
} else if (mode === "deserialize") {
|
||||
polymorphicPropertyName = "serializedName";
|
||||
} else {
|
||||
throw new Error(`The given mode "${mode}" for getting the polymorphic mapper for "${objectName}" is inavlid.`);
|
||||
}
|
||||
const discriminatorAsObject: PolymorphicDiscriminator = mapper.type.polymorphicDiscriminator as PolymorphicDiscriminator;
|
||||
|
||||
if (discriminatorAsObject &&
|
||||
discriminatorAsObject[polymorphicPropertyName] !== null &&
|
||||
discriminatorAsObject[polymorphicPropertyName] !== undefined) {
|
||||
if (object === null || object === undefined) {
|
||||
throw new Error(`${objectName}" cannot be null or undefined. ` +
|
||||
`"${discriminatorAsObject[polymorphicPropertyName]}" is the ` +
|
||||
`polmorphicDiscriminator and is a required property.`);
|
||||
}
|
||||
if (object[discriminatorAsObject[polymorphicPropertyName]] === null ||
|
||||
object[discriminatorAsObject[polymorphicPropertyName]] === undefined) {
|
||||
throw new Error(`No discriminator field "${discriminatorAsObject[polymorphicPropertyName]}" was found in "${objectName}".`);
|
||||
}
|
||||
let indexDiscriminator = undefined;
|
||||
if (object[discriminatorAsObject[polymorphicPropertyName]] === mapper.type.uberParent) {
|
||||
indexDiscriminator = object[discriminatorAsObject[polymorphicPropertyName]];
|
||||
} else {
|
||||
indexDiscriminator = mapper.type.uberParent + "." + object[discriminatorAsObject[polymorphicPropertyName]];
|
||||
}
|
||||
if (!(this.modelMappers as { [key: string]: any }).discriminators[indexDiscriminator]) {
|
||||
throw new Error(`${discriminatorAsObject[polymorphicPropertyName]}": ` +
|
||||
`"${object[discriminatorAsObject[polymorphicPropertyName]]}" in "${objectName}" is not a valid ` +
|
||||
`discriminator as a corresponding model class for the disciminator "${indexDiscriminator}" ` +
|
||||
`was not found in this.modelMappers.discriminators object.`);
|
||||
}
|
||||
mapper = (this.modelMappers as { [key: string]: any }).discriminators[indexDiscriminator];
|
||||
}
|
||||
return mapper;
|
||||
}
|
||||
|
||||
// processes old version of the polymorphicDiscriminator in the mapper.
|
||||
private getPolymorphicMapperStringVersion(mapper: CompositeMapper, object: any, objectName: string): CompositeMapper {
|
||||
// check for polymorphic discriminator
|
||||
const discriminatorAsString: string = mapper.type.polymorphicDiscriminator as string;
|
||||
if (discriminatorAsString !== null && discriminatorAsString !== undefined) {
|
||||
if (object === null || object === undefined) {
|
||||
throw new Error(`${objectName}" cannot be null or undefined. "${discriminatorAsString}" is the ` +
|
||||
`polmorphicDiscriminator and is a required property.`);
|
||||
}
|
||||
if (object[discriminatorAsString] === null || object[discriminatorAsString] === undefined) {
|
||||
throw new Error(`No discriminator field "${discriminatorAsString}" was found in "${objectName}".`);
|
||||
}
|
||||
let indexDiscriminator = undefined;
|
||||
if (object[discriminatorAsString] === mapper.type.uberParent) {
|
||||
indexDiscriminator = object[discriminatorAsString];
|
||||
} else {
|
||||
indexDiscriminator = mapper.type.uberParent + "." + object[discriminatorAsString];
|
||||
}
|
||||
if (!(this.modelMappers as { [key: string]: any }).discriminators[indexDiscriminator]) {
|
||||
throw new Error(`${discriminatorAsString}": ` +
|
||||
`"${object[discriminatorAsString]}" in "${objectName}" is not a valid ` +
|
||||
`discriminator as a corresponding model class for the disciminator "${indexDiscriminator}" ` +
|
||||
`was not found in this.models.discriminators object.`);
|
||||
}
|
||||
mapper = (this.modelMappers as { [key: string]: any }).discriminators[indexDiscriminator];
|
||||
}
|
||||
return mapper;
|
||||
}
|
||||
}
|
||||
|
||||
export interface MapperConstraints {
|
||||
InclusiveMaximum?: number;
|
||||
ExclusiveMaximum?: number;
|
||||
InclusiveMinimum?: number;
|
||||
ExclusiveMinimum?: number;
|
||||
MaxLength?: number;
|
||||
MinLength?: number;
|
||||
Pattern?: string;
|
||||
MaxItems?: number;
|
||||
MinItems?: number;
|
||||
UniqueItems?: true;
|
||||
MultipleOf?: number;
|
||||
}
|
||||
|
||||
export interface BaseMapperType {
|
||||
name: string;
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
export interface Mapper {
|
||||
readOnly?: boolean;
|
||||
isConstant?: boolean;
|
||||
required: boolean;
|
||||
serializedName: string;
|
||||
type: BaseMapperType;
|
||||
defaultValue?: any;
|
||||
constraints?: MapperConstraints;
|
||||
}
|
||||
|
||||
export interface PolymorphicDiscriminator {
|
||||
serializedName: string;
|
||||
clientName: string;
|
||||
[key: string]: string;
|
||||
}
|
||||
|
||||
export interface CompositeMapper extends Mapper {
|
||||
type: {
|
||||
name: "Composite";
|
||||
className: string;
|
||||
modelProperties?: { [propertyName: string]: Mapper };
|
||||
uberParent?: string;
|
||||
polymorphicDiscriminator?: string | PolymorphicDiscriminator;
|
||||
};
|
||||
}
|
||||
|
||||
export interface SequenceMapper extends Mapper {
|
||||
type: {
|
||||
name: "Sequence";
|
||||
element: Mapper;
|
||||
};
|
||||
}
|
||||
|
||||
export interface DictionaryMapper extends Mapper {
|
||||
type: {
|
||||
name: "Dictionary";
|
||||
value: Mapper;
|
||||
};
|
||||
}
|
||||
|
||||
export interface EnumMapper extends Mapper {
|
||||
type: {
|
||||
name: "Enum";
|
||||
allowedValues: Array<any>;
|
||||
};
|
||||
}
|
||||
|
||||
export interface UrlParameterValue {
|
||||
value: string;
|
||||
skipUrlEncoding: boolean;
|
||||
}
|
||||
|
||||
export function serializeObject(toSerialize: any): any {
|
||||
if (toSerialize === null || toSerialize === undefined) return undefined;
|
||||
if (isBuffer(toSerialize)) {
|
||||
toSerialize = toSerialize.toString("base64");
|
||||
return toSerialize;
|
||||
}
|
||||
else if (toSerialize instanceof Date) {
|
||||
return toSerialize.toISOString();
|
||||
}
|
||||
else if (Array.isArray(toSerialize)) {
|
||||
const array = [];
|
||||
for (let i = 0; i < toSerialize.length; i++) {
|
||||
array.push(serializeObject(toSerialize[i]));
|
||||
}
|
||||
return array;
|
||||
} else if (typeof toSerialize === "object") {
|
||||
const dictionary: { [key: string]: any } = {};
|
||||
for (const property in toSerialize) {
|
||||
dictionary[property] = serializeObject(toSerialize[property]);
|
||||
}
|
||||
return dictionary;
|
||||
}
|
||||
return toSerialize;
|
||||
}
|
||||
|
||||
export const MapperType = utils.strEnum([
|
||||
"Base64Url",
|
||||
"Boolean",
|
||||
"ByteArray",
|
||||
"Composite",
|
||||
"Date",
|
||||
"DateTime",
|
||||
"DateTimeRfc1123",
|
||||
"Dictionary",
|
||||
"Enum",
|
||||
"Number",
|
||||
"Object",
|
||||
"Sequence",
|
||||
"String",
|
||||
"Stream",
|
||||
"TimeSpan",
|
||||
"UnixTime"
|
||||
]);
|
|
@ -0,0 +1,147 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
import { RequestPipeline } from "./requestPipeline";
|
||||
import { ServiceClientCredentials } from "./credentials/serviceClientCredentials";
|
||||
import { BaseFilter } from "./filters/baseFilter";
|
||||
import { ExponentialRetryPolicyFilter } from "./filters/exponentialRetryPolicyFilter";
|
||||
import { SystemErrorRetryPolicyFilter } from "./filters/systemErrorRetryPolicyFilter";
|
||||
import { RedirectFilter } from "./filters/redirectFilter";
|
||||
import { SigningFilter } from "./filters/signingFilter";
|
||||
import { RPRegistrationFilter } from "./filters/rpRegistrationFilter";
|
||||
import { MsRestUserAgentFilter } from "./filters/msRestUserAgentFilter";
|
||||
import { WebResource, RequestPrepareOptions } from "./webResource";
|
||||
import { Constants } from "./util/constants";
|
||||
import { HttpOperationResponse } from "./httpOperationResponse";
|
||||
|
||||
/**
|
||||
* Options to be provided while creating the client.
|
||||
*/
|
||||
export interface ServiceClientOptions {
|
||||
/**
|
||||
* @property {RequestInit} [requestOptions] The request options. Detailed info can be found
|
||||
* here https://github.github.io/fetch/#Request
|
||||
*/
|
||||
requestOptions?: RequestInit;
|
||||
/**
|
||||
* @property {Array<BaseFilter>} [filters] An array of filters/interceptors that will
|
||||
* be processed in the request pipeline (before and after) sending the request on the wire.
|
||||
*/
|
||||
filters?: BaseFilter[];
|
||||
/**
|
||||
* @property {bool} [noRetryPolicy] - If set to true, turn off the default retry policy.
|
||||
*/
|
||||
noRetryPolicy?: boolean;
|
||||
/**
|
||||
* @property {number} [rpRegistrationRetryTimeout] - Gets or sets the retry timeout
|
||||
* in seconds for AutomaticRPRegistration. Default value is 30.
|
||||
*/
|
||||
rpRegistrationRetryTimeout?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* @class
|
||||
* Initializes a new instance of the ServiceClient.
|
||||
*/
|
||||
export class ServiceClient {
|
||||
/**
|
||||
* The string to be appended to the User-Agent header while sending the request.
|
||||
* This will be applicable only for node.js environment as the fetch library in browser does not allow setting custom UA.
|
||||
* @property {Array<string>} value - An array of string that need to be appended to the User-Agent request header.
|
||||
*/
|
||||
userAgentInfo: { value: Array<string> };
|
||||
|
||||
/**
|
||||
* The request pipeline that provides hooks for adding custom filters.
|
||||
* The before filters get executed before sending the request and the after filters get executed after receiving the response.
|
||||
*/
|
||||
pipeline: Function;
|
||||
|
||||
/**
|
||||
* The ServiceClient constructor
|
||||
* @constructor
|
||||
* @param {ServiceClientCredentials }[credentials] - BasicAuthenticationCredentials or
|
||||
* TokenCredentials object used for authentication.
|
||||
* @param { ServiceClientOptions } [options] The service client options that govern the behavior of the client.
|
||||
*/
|
||||
constructor(credentials?: ServiceClientCredentials, options?: ServiceClientOptions) {
|
||||
if (!options) {
|
||||
options = {};
|
||||
}
|
||||
|
||||
if (!options.requestOptions) {
|
||||
options.requestOptions = {};
|
||||
}
|
||||
|
||||
if (!options.filters) {
|
||||
options.filters = [];
|
||||
}
|
||||
|
||||
this.userAgentInfo = { value: [] };
|
||||
|
||||
if (credentials && !credentials.signRequest) {
|
||||
throw new Error("credentials argument needs to implement signRequest method");
|
||||
}
|
||||
|
||||
try {
|
||||
const moduleName = "ms-rest-js";
|
||||
const moduleVersion = Constants.msRestVersion;
|
||||
this.addUserAgentInfo(`${moduleName}/${moduleVersion}`);
|
||||
} catch (err) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
if (credentials) {
|
||||
options.filters.push(new SigningFilter(credentials));
|
||||
}
|
||||
|
||||
options.filters.push(new MsRestUserAgentFilter(this.userAgentInfo.value));
|
||||
options.filters.push(new RedirectFilter());
|
||||
options.filters.push(new RPRegistrationFilter(options.rpRegistrationRetryTimeout));
|
||||
|
||||
if (!options.noRetryPolicy) {
|
||||
options.filters.push(new ExponentialRetryPolicyFilter());
|
||||
options.filters.push(new SystemErrorRetryPolicyFilter());
|
||||
}
|
||||
|
||||
this.pipeline = new RequestPipeline(options.filters, options.requestOptions).create();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds custom information to user agent header
|
||||
* @param {any} additionalUserAgentInfo - information to be added to user agent header, as string.
|
||||
*/
|
||||
addUserAgentInfo(additionalUserAgentInfo: string): void {
|
||||
if (this.userAgentInfo.value.indexOf(additionalUserAgentInfo) === -1) {
|
||||
this.userAgentInfo.value.push(additionalUserAgentInfo);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
async sendRequest(options: RequestPrepareOptions | WebResource): 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: WebResource;
|
||||
try {
|
||||
if (options instanceof WebResource) {
|
||||
options.validateRequestProperties();
|
||||
httpRequest = options;
|
||||
} else {
|
||||
httpRequest = new WebResource();
|
||||
httpRequest = httpRequest.prepare(options);
|
||||
}
|
||||
} catch (error) {
|
||||
return Promise.reject(error);
|
||||
}
|
||||
// send request
|
||||
let operationResponse: HttpOperationResponse;
|
||||
try {
|
||||
operationResponse = await this.pipeline(httpRequest);
|
||||
} catch (err) {
|
||||
return Promise.reject(err);
|
||||
}
|
||||
return Promise.resolve(operationResponse);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
// 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: "0.1.0",
|
||||
|
||||
/**
|
||||
* 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",
|
||||
|
||||
HttpConstants: {
|
||||
/**
|
||||
* Http Verbs
|
||||
*
|
||||
* @const
|
||||
* @enum {string}
|
||||
*/
|
||||
HttpVerbs: {
|
||||
PUT: "PUT",
|
||||
GET: "GET",
|
||||
DELETE: "DELETE",
|
||||
POST: "POST",
|
||||
MERGE: "MERGE",
|
||||
HEAD: "HEAD",
|
||||
PATCH: "PATCH"
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* Defines constants for use with HTTP headers.
|
||||
*/
|
||||
HeaderConstants: {
|
||||
/**
|
||||
* The Authorization header.
|
||||
*
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
AUTHORIZATION: "authorization",
|
||||
|
||||
AUTHORIZATION_SCHEME: "Bearer",
|
||||
|
||||
/**
|
||||
* The UserAgent header.
|
||||
*
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
USER_AGENT: "User-Agent"
|
||||
}
|
||||
};
|
|
@ -0,0 +1,323 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
import * as uuid from "uuid";
|
||||
import * as FormData from "form-data";
|
||||
import { WebResource } from "../webResource";
|
||||
import { Constants } from "./constants";
|
||||
import { RestError } from "../restError";
|
||||
import { HttpOperationResponse } from "../httpOperationResponse";
|
||||
|
||||
/**
|
||||
* Provides the fetch() method based on the environment.
|
||||
* @returns {fetch} fetch - The fetch() method available in the environment to make requests
|
||||
*/
|
||||
export function getFetch(): Function {
|
||||
// using window.Fetch in Edge gives a TypeMismatchError
|
||||
// (https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/8546263/).
|
||||
// Hence we will be using the fetch-ponyfill for Edge.
|
||||
if (typeof window !== "undefined" && window.fetch && window.navigator &&
|
||||
window.navigator.userAgent && window.navigator.userAgent.indexOf("Edge/") === -1) {
|
||||
return window.fetch.bind(window);
|
||||
}
|
||||
return require("fetch-ponyfill")({ useCookie: true }).fetch;
|
||||
}
|
||||
|
||||
/**
|
||||
* A constant that provides the fetch() method based on the environment.
|
||||
*/
|
||||
export const myFetch = getFetch();
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a value is null or undefined.
|
||||
*
|
||||
* @param {object} value The value to check for null or undefined.
|
||||
* @return {boolean} True if the value is null or undefined, false otherwise.
|
||||
*/
|
||||
// TODO: Audit the usages of this and remove them.
|
||||
// Read: https://medium.com/@basarat/null-vs-undefined-in-typescript-land-dc0c7a5f240a
|
||||
// https://github.com/Microsoft/TypeScript/issues/7426
|
||||
export function objectIsNull(value: any): boolean {
|
||||
return value === null || value === undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes an URI.
|
||||
*
|
||||
* @param {string} uri The URI to be encoded.
|
||||
* @return {string} The encoded URI.
|
||||
*/
|
||||
export function encodeUri(uri: 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 {nodeFetch.Response} response - The Http Response
|
||||
*
|
||||
* @return {object} strippedResponse - The stripped version of Http Response.
|
||||
*/
|
||||
export function stripResponse(response: Response) {
|
||||
const strippedResponse: any = {};
|
||||
strippedResponse.body = response.body;
|
||||
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 {object} request - The Http Request object
|
||||
*
|
||||
* @return {object} strippedRequest - The stripped version of Http Request.
|
||||
*/
|
||||
export function stripRequest(request: WebResource): WebResource {
|
||||
let strippedRequest = new WebResource();
|
||||
try {
|
||||
strippedRequest = JSON.parse(JSON.stringify(request));
|
||||
if (strippedRequest.headers && strippedRequest.headers.Authorization) {
|
||||
delete strippedRequest.headers.Authorization;
|
||||
} else if (strippedRequest.headers && strippedRequest.headers.authorization) {
|
||||
delete strippedRequest.headers.authorization;
|
||||
}
|
||||
} catch (err) {
|
||||
const errMsg = err.message;
|
||||
err.message = `Error - "${errMsg}" occured while creating a stripped version of the request object - "${request}".`;
|
||||
return err;
|
||||
}
|
||||
|
||||
return strippedRequest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the given uuid as a string
|
||||
*
|
||||
* @param {string} uuid - The uuid as a string that needs to be validated
|
||||
*
|
||||
* @return {boolean} result - 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 {array} result - 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 uuid.v4();
|
||||
}
|
||||
|
||||
/*
|
||||
* 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} target - 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));
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility function to create a K:V from a list of strings
|
||||
*/
|
||||
export function strEnum<T extends string>(o: Array<T>): {[K in T]: K} {
|
||||
return o.reduce((res, key: string) => {
|
||||
res[key] = key;
|
||||
return res;
|
||||
}, Object.create(null));
|
||||
}
|
||||
|
||||
/**
|
||||
* Service callback that is returned for REST requests initiated by the service client.
|
||||
*
|
||||
* @property {Error|RestError} err - The error occurred if any, while executing the request; otherwise null
|
||||
* @property {TResult} result - The deserialized response body if an error did not occur.
|
||||
* @property {WebResource} request - The raw/actual request sent to the server if an error did not occur.
|
||||
* @property {Response} response - The raw/actual response from the server if an error did not occur.
|
||||
*/
|
||||
export interface ServiceCallback<TResult> { (err: Error | RestError, result?: TResult, request?: WebResource, response?: Response): void; }
|
||||
|
||||
/**
|
||||
* Converts a Promise to a callback.
|
||||
* @param {Promise<any>} promise - The Promise to be converted to a callback
|
||||
* @returns {Function} fn - A function that takes the callback (cb: Function): void
|
||||
*/
|
||||
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) => {
|
||||
process.nextTick(cb, undefined, data);
|
||||
}, (err: Error) => {
|
||||
process.nextTick(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} fn - 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.bodyAsJson as T, data.request, data.response);
|
||||
}, (err: Error) => {
|
||||
process.nextTick(cb, err);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the request and returns the received response.
|
||||
* @param {WebResource} options - The request to be sent.
|
||||
* @returns {Promise<HttpOperationResponse} operationResponse - The response object.
|
||||
*/
|
||||
export async function dispatchRequest(options: WebResource): Promise<HttpOperationResponse> {
|
||||
if (!options) {
|
||||
return Promise.reject(new Error("options (WebResource) cannot be null or undefined and must be of type object."));
|
||||
}
|
||||
|
||||
if (options.formData) {
|
||||
const formData: any = options.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 in formData) {
|
||||
if (formData.hasOwnProperty(formKey)) {
|
||||
const formValue = formData[formKey];
|
||||
if (formValue instanceof Array) {
|
||||
for (let j = 0; j < formValue.length; j++) {
|
||||
appendFormValue(formKey, formValue[j]);
|
||||
}
|
||||
} else {
|
||||
appendFormValue(formKey, formValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
options.body = requestForm;
|
||||
options.formData = undefined;
|
||||
if (options.headers && options.headers["Content-Type"] &&
|
||||
options.headers["Content-Type"].indexOf("multipart/form-data") > -1 && typeof requestForm.getBoundary === "function") {
|
||||
options.headers["Content-Type"] = `multipart/form-data; boundary=${requestForm.getBoundary()}`;
|
||||
}
|
||||
}
|
||||
let res: Response;
|
||||
try {
|
||||
res = await myFetch(options.url, options);
|
||||
} catch (err) {
|
||||
return Promise.reject(err);
|
||||
}
|
||||
const operationResponse = new HttpOperationResponse(options, res, res.body);
|
||||
if (!options.rawResponse) {
|
||||
try {
|
||||
operationResponse.bodyAsText = await res.text();
|
||||
} catch (err) {
|
||||
const msg = `Error "${err}" occured while converting the raw response body into string.`;
|
||||
const errCode = err.code || "RAWTEXT_CONVERSION_ERROR";
|
||||
const e = new RestError(msg, errCode, res.status, options, res, res.body);
|
||||
return Promise.reject(e);
|
||||
}
|
||||
try {
|
||||
if (operationResponse.bodyAsText) {
|
||||
operationResponse.bodyAsJson = JSON.parse(operationResponse.bodyAsText);
|
||||
}
|
||||
} catch (err) {
|
||||
const msg = `Error "${err}" occured while executing JSON.parse on the response body - ${operationResponse.bodyAsText}.`;
|
||||
const errCode = err.code || "JSON_PARSE_ERROR";
|
||||
const e = new RestError(msg, errCode, res.status, options, res, operationResponse.bodyAsText);
|
||||
return Promise.reject(e);
|
||||
}
|
||||
}
|
||||
return Promise.resolve(operationResponse);
|
||||
}
|
|
@ -0,0 +1,307 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
import { generateUuid } from "./util/utils";
|
||||
import { Serializer, Mapper } from "./serializer";
|
||||
export type HttpMethods = "GET" | "PUT" | "POST" | "DELETE" | "PATCH" | "HEAD" | "OPTIONS" | "TRACE";
|
||||
|
||||
/**
|
||||
* 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: { [key: string]: any; } = {};
|
||||
rawResponse?: boolean;
|
||||
formData?: any;
|
||||
query?: { [key: string]: any; };
|
||||
|
||||
|
||||
constructor(url?: string, method?: HttpMethods, body?: any, query?: { [key: string]: any; }, headers: { [key: string]: any; } = {}, rawResponse = false) {
|
||||
this.rawResponse = rawResponse;
|
||||
this.url = url || "";
|
||||
this.method = method || "GET";
|
||||
this.headers = headers || {};
|
||||
this.body = body;
|
||||
this.query = query;
|
||||
this.formData = undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 || !this.url || !this.headers["Content-Type"] || !this.headers["accept-language"]) {
|
||||
throw new Error("method, url, headers[\"Content-Type\"], headers[\"accept-language\"] are " +
|
||||
"required properties before making a request. Either provide them or use WebResource.prepare() method.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the request.
|
||||
* @param {RequestPrepareOptions} options - Options to provide for preparing the request.
|
||||
* @returns {object} WebResource Returns the prepared WebResource (HTTP Request) object that needs to be given to the request pipeline.
|
||||
*/
|
||||
prepare(options: RequestPrepareOptions) {
|
||||
if (options === null || options === undefined || typeof options !== "object") {
|
||||
throw new Error("options cannot be null or undefined and must be of type object");
|
||||
}
|
||||
|
||||
if (options.method === null || options.method === undefined || typeof options.method.valueOf() !== "string") {
|
||||
throw new Error("options.method cannot be null or undefined and it must be of type string.");
|
||||
}
|
||||
|
||||
if (options.url && options.pathTemplate) {
|
||||
throw new Error("options.url and options.pathTemplate are mutually exclusive. Please provide either of them.");
|
||||
}
|
||||
|
||||
|
||||
if ((options.pathTemplate === null || options.pathTemplate === undefined || typeof options.pathTemplate.valueOf() !== "string") && (options.url === null || options.url === undefined || typeof options.url.valueOf() !== "string")) {
|
||||
throw new Error("Please provide either options.pathTemplate or options.url. Currently none of them were provided.");
|
||||
}
|
||||
|
||||
// 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) {
|
||||
if (typeof options.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("/") ? "" : "/") + (options.pathTemplate.startsWith("/") ? options.pathTemplate.slice(1) : options.pathTemplate);
|
||||
const segments = url.match(/({\w*\s*\w*})/ig);
|
||||
if (segments && segments.length) {
|
||||
if (options.pathParameters === null || options.pathParameters === undefined || typeof options.pathParameters !== "object") {
|
||||
throw new Error(`pathTemplate: ${options.pathTemplate} has been provided. Hence, options.pathParameters ` +
|
||||
`cannot be null or undefined and must be of type "object".`);
|
||||
}
|
||||
segments.forEach(function (item) {
|
||||
const pathParamName = item.slice(1, -1);
|
||||
const pathParam = (options.pathParameters as { [key: string]: any })[pathParamName];
|
||||
if (pathParam === null || pathParam === undefined || !(typeof pathParam === "string" || typeof pathParam === "object")) {
|
||||
throw new Error(`pathTemplate: ${options.pathTemplate} contains the path parameter ${pathParamName}` +
|
||||
` however, it is not present in ${options.pathParameters} - ${JSON.stringify(options.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) {
|
||||
if (typeof options.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 = [];
|
||||
const queryParameters = options.queryParameters;
|
||||
// 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 in headers) {
|
||||
if (headers.hasOwnProperty(headerName)) {
|
||||
this.headers[headerName] = headers[headerName];
|
||||
}
|
||||
}
|
||||
}
|
||||
// ensure accept-language is set correctly
|
||||
if (!this.headers["accept-language"]) {
|
||||
this.headers["accept-language"] = "en-US";
|
||||
}
|
||||
// ensure the request-id is set correctly
|
||||
if (!this.headers["x-ms-client-request-id"] && !options.disableClientRequestId) {
|
||||
this.headers["x-ms-client-request-id"] = generateUuid();
|
||||
}
|
||||
|
||||
// default
|
||||
if (!this.headers["Content-Type"]) {
|
||||
this.headers["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 = undefined;
|
||||
if (options.body !== null && 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) {
|
||||
this.body = options.body;
|
||||
if (!this.headers["Transfer-Encoding"]) {
|
||||
this.headers["Transfer-Encoding"] = "chunked";
|
||||
}
|
||||
if (this.headers["Content-Type"] !== "application/octet-stream") {
|
||||
this.headers["Content-Type"] = "application/octet-stream";
|
||||
}
|
||||
} else {
|
||||
let serializedBody = undefined;
|
||||
if (options.serializationMapper) {
|
||||
serializedBody = new Serializer(options.mappers).serialize(options.serializationMapper, options.body, "requestBody");
|
||||
}
|
||||
if (options.disableJsonStringifyOnBody) {
|
||||
this.body = serializedBody || options.body;
|
||||
} else {
|
||||
this.body = serializedBody ? JSON.stringify(serializedBody) : JSON.stringify(options.body);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the request.
|
||||
* @param {object} options The request options that should be provided to send a request successfully
|
||||
* @param {string} options.method The HTTP request method. Valid values are "GET", "PUT", "HEAD", "DELETE", "OPTIONS", "POST", "PATCH".
|
||||
* @param {string} [options.url] 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.
|
||||
* @param {object} [options.queryParameters] 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.
|
||||
* @param {string} [options.pathTemplate] 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}"
|
||||
* @param {string} [options.baseUrl] The base url of the request. Default value is: "https://management.azure.com". This is applicable only with
|
||||
* options.pathTemplate. If you are providing options.url then it is expected that you provide the complete url.
|
||||
* @param {object} [options.pathParameters] 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" }.
|
||||
* @param {object} [options.headers] 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
|
||||
* @param {boolean} [options.disableClientRequestId] When set to true, instructs the client to not set "x-ms-client-request-id" header to a new Guid().
|
||||
* @param {object|string|boolean|array|number|null|undefined} [options.body] - The request body. It can be of any type. This method will JSON.stringify() the request body.
|
||||
* @param {object} [options.serializationMapper] - Provides information on how to serialize the request body.
|
||||
* @param {object} [options.mappers] - A dictionary of mappers that may be used while [de]serialization.
|
||||
* @param {object} [options.deserializationMapper] - Provides information on how to deserialize the response body.
|
||||
* @param {boolean} [options.disableJsonStringifyOnBody] - Indicates whether this method should JSON.stringify() the request body. Default value: false.
|
||||
* @param {boolean} [options.bodyIsStream] - Indicates whether the request body is a stream (useful for file upload scenarios).
|
||||
* @returns {object} WebResource Returns the prepared WebResource (HTTP Request) object that needs to be given to the request pipeline.
|
||||
*/
|
||||
export interface RequestPrepareOptions {
|
||||
method: HttpMethods;
|
||||
url?: string;
|
||||
queryParameters?: { [key: string]: any } | ParameterValue;
|
||||
pathTemplate?: string;
|
||||
baseUrl?: string;
|
||||
pathParameters?: { [key: string]: any } | ParameterValue;
|
||||
headers?: { [key: string]: any };
|
||||
disableClientRequestId?: boolean;
|
||||
body?: any;
|
||||
serializationMapper?: Mapper;
|
||||
mappers?: { [x: string]: any };
|
||||
deserializationMapper?: object;
|
||||
disableJsonStringifyOnBody?: boolean;
|
||||
bodyIsStream?: 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 };
|
||||
[key: string]: any;
|
||||
}
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,67 @@
|
|||
{
|
||||
"name": "ms-rest-js",
|
||||
"author": {
|
||||
"name": "Microsoft Corporation",
|
||||
"email": "azsdkteam@microsoft.com",
|
||||
"url": "https://github.com/Azure/azure-sdk-for-node"
|
||||
},
|
||||
"version": "0.1.0",
|
||||
"description": "Client Runtime for Node.js client libraries generated using AutoRest",
|
||||
"tags": [
|
||||
"node",
|
||||
"microsoft",
|
||||
"autorest",
|
||||
"clientruntime"
|
||||
],
|
||||
"keywords": [
|
||||
"node",
|
||||
"microsoft",
|
||||
"autorest",
|
||||
"clientruntime"
|
||||
],
|
||||
"main": "./dist/lib/msRest.js",
|
||||
"types": "./typings/lib/msRest.d.ts",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/form-data": "^2.2.0",
|
||||
"@types/node": "^8.0.28",
|
||||
"@types/node-fetch": "^1.6.7",
|
||||
"@types/uuid": "^3.4.1",
|
||||
"@types/is-stream": "^1.1.0",
|
||||
"fetch-cookie": "^0.6.0",
|
||||
"form-data": "^2.3.1",
|
||||
"is-stream": "^1.1.0",
|
||||
"url-parse": "^1.1.9",
|
||||
"moment": "^2.18.1",
|
||||
"is-buffer": "^1.1.5",
|
||||
"uuid": "^3.1.0",
|
||||
"detect-node": "^2.0.3",
|
||||
"fetch-ponyfill": "amarzavery/fetch-ponyfill#master"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/mocha": "^2.2.40",
|
||||
"@types/should": "^8.1.30",
|
||||
"mocha": "^3.2.0",
|
||||
"should": "5.2.0",
|
||||
"ts-loader": "^2.3.7",
|
||||
"tslint": "^5.7.0",
|
||||
"typescript": "^2.5.2",
|
||||
"webpack": "^3.5.6",
|
||||
"uglify-es": "^3.1.0"
|
||||
},
|
||||
"homepage": "https://github.com/Azure/azure-sdk-for-node/runtime/ms-rest",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git@github.com:Azure/azure-sdk-for-node.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "http://github.com/Azure/azure-sdk-for-node/issues"
|
||||
},
|
||||
"scripts": {
|
||||
"tsc": "tsc -p tsconfig.json",
|
||||
"test": "npm install && npm -s run-script unit",
|
||||
"unit": "mocha -t 50000 dist/test",
|
||||
"uglify": "node node_modules/uglify-es/bin/uglifyjs --source-map -c -m -o msRestBundle.min.js msRestBundle.js",
|
||||
"build": "npm -s run-script tsc && webpack && npm -s run-script uglify"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<title>My Todos</title>
|
||||
<script type="text/javascript" src="../msRestBundle.js"></script>
|
||||
<script type="text/javascript">
|
||||
document.write('hello world');
|
||||
const msRest = className;
|
||||
const subscriptionId = "00977cdb-163f-435f-9c32-39ec8ae61f4d";
|
||||
const token = "token";
|
||||
const creds = new msRest.TokenCredentials(token);
|
||||
const client = new msRest.ServiceClient(creds);
|
||||
const req = {
|
||||
url: `https://management.azure.com/subscriptions/${subscriptionId}/providers/Microsoft.Storage/storageAccounts?api-version=2015-06-15`,
|
||||
method: "GET"
|
||||
};
|
||||
client.sendRequest(req).then((res) => { document.write(res.bodyAsText); }).catch((err) => { console.log(err); });
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -0,0 +1,26 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const msRest = require("../lib/msRest");
|
||||
const clientOptions = {
|
||||
filters: [new msRest.LogFilter()]
|
||||
};
|
||||
const subscriptionId = process.env["AZURE_SUBSCRIPTION_ID"] || "subscriptionId";
|
||||
// An easy way to get the token
|
||||
// 1. Go to this test drive link https://azure.github.io/projects/apis and authenticate by clicking on Authorize. Check the user impersoantion checkbox in the popup.
|
||||
// 1.1 select a subscription of your choice
|
||||
// 1.2 select the storage-2015-06-15 option from the first drop down list
|
||||
// 1.3 expand the url to list storage accounts in a subscription
|
||||
// 1.4 click on try it out button.
|
||||
// 1.5 in the curl tab you will see the actual curl request that has the bearer token in it
|
||||
// 1.6 copy paste that token here. That token is valid for 1 hour
|
||||
const token = process.env["ACCESS_TOKEN"] || "token";
|
||||
const creds = new msRest.TokenCredentials(token);
|
||||
const client = new msRest.ServiceClient(creds, clientOptions);
|
||||
const req = {
|
||||
url: `https://management.azure.com/subscriptions/${subscriptionId}/providers/Microsoft.Storage/storageAccounts?api-version=2015-06-15`,
|
||||
method: 'GET'
|
||||
};
|
||||
client.sendRequest(req).then(function (res) {
|
||||
console.log(res.bodyAsText);
|
||||
});
|
||||
//# sourceMappingURL=node-sample.js.map
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"node-sample.js","sourceRoot":"","sources":["../../samples/node-sample.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,wCAAwC;AACxC,MAAM,aAAa,GAAgC;IACjD,OAAO,EAAE,CAAC,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;CAClC,CAAC;AAEF,MAAM,cAAc,GAAG,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,IAAI,gBAAgB,CAAC;AAChF,+BAA+B;AAC/B,qKAAqK;AACrK,2CAA2C;AAC3C,yEAAyE;AACzE,gEAAgE;AAChE,kCAAkC;AAClC,2FAA2F;AAC3F,iEAAiE;AACjE,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,OAAO,CAAC;AACrD,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC;AACjD,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,aAAa,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC;AAC9D,MAAM,GAAG,GAAiC;IACxC,GAAG,EAAE,8CAA8C,cAAc,qEAAqE;IACtI,MAAM,EAAE,KAAK;CACd,CAAC;AAEF,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,UAAU,GAAiC;IACtE,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;AAC9B,CAAC,CAAC,CAAC"}
|
|
@ -0,0 +1,28 @@
|
|||
"use strict";
|
||||
|
||||
import * as msRest from "../lib/msRest";
|
||||
const clientOptions: msRest.ServiceClientOptions = {
|
||||
filters: [new msRest.LogFilter()]
|
||||
};
|
||||
|
||||
const subscriptionId = process.env["AZURE_SUBSCRIPTION_ID"] || "subscriptionId";
|
||||
// An easy way to get the token
|
||||
// 1. Go to this test drive link https://azure.github.io/projects/apis and authenticate by clicking on Authorize. Check the user impersoantion checkbox in the popup.
|
||||
// 1.1 select a subscription of your choice
|
||||
// 1.2 select the storage-2015-06-15 option from the first drop down list
|
||||
// 1.3 expand the url to list storage accounts in a subscription
|
||||
// 1.4 click on try it out button.
|
||||
// 1.5 in the curl tab you will see the actual curl request that has the bearer token in it
|
||||
// 1.6 copy paste that token here. That token is valid for 1 hour
|
||||
const token = process.env["ACCESS_TOKEN"] || "token";
|
||||
const creds = new msRest.TokenCredentials(token);
|
||||
const client = new msRest.ServiceClient(creds, clientOptions);
|
||||
const req: msRest.RequestPrepareOptions = {
|
||||
url: `https://management.azure.com/subscriptions/${subscriptionId}/providers/Microsoft.Storage/storageAccounts?api-version=2015-06-15`,
|
||||
method: 'GET'
|
||||
};
|
||||
|
||||
client.sendRequest(req).then(function (res: msRest.HttpOperationResponse) {
|
||||
console.log(res.bodyAsText);
|
||||
});
|
||||
|
|
@ -0,0 +1,109 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
import * as msRest from "../lib/msRest";
|
||||
const should = require("should");
|
||||
const TokenCredentials = msRest.TokenCredentials;
|
||||
const BasicAuthenticationCredentials = msRest.BasicAuthenticationCredentials;
|
||||
const dummyToken = "A-dummy-access-token";
|
||||
const fakeScheme = "fake-auth-scheme";
|
||||
const dummyuserName = "dummy@mummy.com";
|
||||
const dummyPassword = "IL0veDummies";
|
||||
|
||||
describe("Token credentials", () => {
|
||||
describe("usage", () => {
|
||||
it("should set auth header with bearer scheme in request", (done) => {
|
||||
const creds = new TokenCredentials(dummyToken);
|
||||
const request = new msRest.WebResource();
|
||||
request.headers = {};
|
||||
|
||||
creds.signRequest(request).then((signedRequest: msRest.WebResource) => {
|
||||
should.exist(signedRequest.headers["authorization"]);
|
||||
|
||||
signedRequest.headers["authorization"].should.match(new RegExp("^Bearer\\s+" + dummyToken + "$"));
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it("should set auth header with custom scheme in request", (done) => {
|
||||
const creds = new TokenCredentials(dummyToken, fakeScheme);
|
||||
const request = new msRest.WebResource();
|
||||
request.headers = {};
|
||||
creds.signRequest(request).then((signedRequest: msRest.WebResource) => {
|
||||
should.exist(signedRequest.headers["authorization"]);
|
||||
signedRequest.headers["authorization"].should.match(new RegExp("^" + fakeScheme + "\\s+" + dummyToken + "$"));
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("construction", () => {
|
||||
|
||||
it("should succeed with token", () => {
|
||||
(() => {
|
||||
new TokenCredentials(dummyToken);
|
||||
}).should.not.throw();
|
||||
});
|
||||
|
||||
// it("should fail without credentials", () => {
|
||||
// (() => {
|
||||
// new TokenCredentials();
|
||||
// }).should.throw();
|
||||
// });
|
||||
|
||||
// it("should fail without token", () => {
|
||||
// (() => {
|
||||
// new TokenCredentials(null, fakeScheme);
|
||||
// }).should.throw();
|
||||
// });
|
||||
});
|
||||
});
|
||||
|
||||
describe("Basic Authentication credentials", () => {
|
||||
const encodedCredentials = Buffer.from(dummyuserName + ":" + dummyPassword).toString("base64");
|
||||
describe("usage", () => {
|
||||
it("should base64 encode the username and password and set auth header with baisc scheme in request", (done) => {
|
||||
const creds = new BasicAuthenticationCredentials(dummyuserName, dummyPassword);
|
||||
const request = new msRest.WebResource();
|
||||
request.headers = {};
|
||||
creds.signRequest(request).then((signedRequest: msRest.WebResource) => {
|
||||
signedRequest.headers.should.have.property("authorization");
|
||||
signedRequest.headers["authorization"].should.match(new RegExp("^Basic\\s+" + encodedCredentials + "$"));
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it("should base64 encode the username and password and set auth header with custom scheme in request", (done) => {
|
||||
const creds = new BasicAuthenticationCredentials(dummyuserName, dummyPassword, fakeScheme);
|
||||
const request = new msRest.WebResource();
|
||||
request.headers = {};
|
||||
|
||||
creds.signRequest(request).then((signedRequest: msRest.WebResource) => {
|
||||
signedRequest.headers.should.have.property("authorization");
|
||||
signedRequest.headers["authorization"].should.match(new RegExp("^" + fakeScheme + "\\s+" + encodedCredentials + "$"));
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("construction", () => {
|
||||
|
||||
it("should succeed with userName and password", () => {
|
||||
(() => {
|
||||
new BasicAuthenticationCredentials(dummyuserName, dummyPassword);
|
||||
}).should.not.throw();
|
||||
});
|
||||
|
||||
// it("should fail without credentials", () => {
|
||||
// (() => {
|
||||
// new BasicAuthenticationCredentials(null, null);
|
||||
// }).should.throw();
|
||||
// });
|
||||
|
||||
// it("should fail without userName and password", () => {
|
||||
// (() => {
|
||||
// new BasicAuthenticationCredentials(null, null, fakeScheme);
|
||||
// }).should.throw();
|
||||
// });
|
||||
});
|
||||
});
|
|
@ -0,0 +1,592 @@
|
|||
/*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for
|
||||
* license information.
|
||||
*/
|
||||
let internalMappers: any = {};
|
||||
|
||||
internalMappers.Cat = {
|
||||
required: false,
|
||||
serializedName: "cat",
|
||||
type: {
|
||||
name: "Composite",
|
||||
className: "Cat",
|
||||
modelProperties: {
|
||||
id: {
|
||||
required: false,
|
||||
serializedName: "id",
|
||||
type: {
|
||||
name: "Number"
|
||||
}
|
||||
},
|
||||
name: {
|
||||
required: false,
|
||||
serializedName: "name",
|
||||
type: {
|
||||
name: "String"
|
||||
}
|
||||
},
|
||||
pettype: {
|
||||
required: true,
|
||||
serializedName: "pet\\.type",
|
||||
type: {
|
||||
name: "String"
|
||||
}
|
||||
},
|
||||
color: {
|
||||
required: false,
|
||||
serializedName: "color",
|
||||
type: {
|
||||
name: "String"
|
||||
}
|
||||
},
|
||||
hates: {
|
||||
required: false,
|
||||
serializedName: "hates",
|
||||
type: {
|
||||
name: "Sequence",
|
||||
element: {
|
||||
required: false,
|
||||
serializedName: "DogElementType",
|
||||
type: {
|
||||
name: "Composite",
|
||||
className: "Dog"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
internalMappers.Dog = {
|
||||
required: false,
|
||||
serializedName: "dog",
|
||||
type: {
|
||||
name: "Composite",
|
||||
className: "Dog",
|
||||
modelProperties: {
|
||||
id: {
|
||||
required: false,
|
||||
serializedName: "id",
|
||||
type: {
|
||||
name: "Number"
|
||||
}
|
||||
},
|
||||
name: {
|
||||
required: false,
|
||||
serializedName: "name",
|
||||
type: {
|
||||
name: "String"
|
||||
}
|
||||
},
|
||||
pettype: {
|
||||
required: true,
|
||||
serializedName: "pet\\.type",
|
||||
type: {
|
||||
name: "String"
|
||||
}
|
||||
},
|
||||
food: {
|
||||
required: false,
|
||||
serializedName: "food",
|
||||
type: {
|
||||
name: "String"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
internalMappers.Fish = {
|
||||
required: false,
|
||||
serializedName: "Fish",
|
||||
type: {
|
||||
name: "Composite",
|
||||
polymorphicDiscriminator: {
|
||||
serializedName: "fish.type",
|
||||
clientName: "fishtype"
|
||||
},
|
||||
uberParent: "Fish",
|
||||
className: "Fish",
|
||||
modelProperties: {
|
||||
species: {
|
||||
required: false,
|
||||
serializedName: "species",
|
||||
type: {
|
||||
name: "String"
|
||||
}
|
||||
},
|
||||
length: {
|
||||
required: true,
|
||||
serializedName: "length",
|
||||
type: {
|
||||
name: "Number"
|
||||
}
|
||||
},
|
||||
siblings: {
|
||||
required: false,
|
||||
serializedName: "siblings",
|
||||
type: {
|
||||
name: "Sequence",
|
||||
element: {
|
||||
required: false,
|
||||
serializedName: "FishElementType",
|
||||
type: {
|
||||
name: "Composite",
|
||||
polymorphicDiscriminator: {
|
||||
serializedName: "fish.type",
|
||||
clientName: "fishtype"
|
||||
},
|
||||
uberParent: "Fish",
|
||||
className: "Fish"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
fishtype: {
|
||||
required: true,
|
||||
serializedName: "fish\\.type",
|
||||
type: {
|
||||
name: "String"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
internalMappers.Invoice = {
|
||||
required: false,
|
||||
serializedName: "Invoice",
|
||||
type: {
|
||||
name: "Composite",
|
||||
className: "Invoice",
|
||||
modelProperties: {
|
||||
invId: {
|
||||
serializedName: "invoiceId",
|
||||
required: true,
|
||||
type: {
|
||||
name: "Number"
|
||||
}
|
||||
},
|
||||
invDate: {
|
||||
serializedName: "invDate",
|
||||
required: false,
|
||||
type: {
|
||||
name: "Date"
|
||||
}
|
||||
},
|
||||
invProducts: {
|
||||
serializedName: "invProducts",
|
||||
required: false,
|
||||
type: {
|
||||
name: "Sequence",
|
||||
element: {
|
||||
type: {
|
||||
name: "Dictionary",
|
||||
value: {
|
||||
type: {
|
||||
name: "Composite",
|
||||
className: "Product"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
internalMappers.Pet = {
|
||||
required: false,
|
||||
serializedName: "pet",
|
||||
type: {
|
||||
name: "Composite",
|
||||
className: "Pet",
|
||||
polymorphicDiscriminator: "pet.type",
|
||||
modelProperties: {
|
||||
id: {
|
||||
required: false,
|
||||
serializedName: "id",
|
||||
type: {
|
||||
name: "Number"
|
||||
}
|
||||
},
|
||||
name: {
|
||||
required: false,
|
||||
serializedName: "name",
|
||||
type: {
|
||||
name: "String"
|
||||
}
|
||||
},
|
||||
pettype: {
|
||||
required: true,
|
||||
serializedName: "pet\\.type",
|
||||
type: {
|
||||
name: "String"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
internalMappers.PetGallery = {
|
||||
required: false,
|
||||
serializedName: "PetGallery",
|
||||
type: {
|
||||
name: "Composite",
|
||||
className: "PetGallery",
|
||||
modelProperties: {
|
||||
id: {
|
||||
required: false,
|
||||
serializedName: "id",
|
||||
type: {
|
||||
name: "Number"
|
||||
}
|
||||
},
|
||||
name: {
|
||||
required: false,
|
||||
serializedName: "name",
|
||||
type: {
|
||||
name: "String"
|
||||
}
|
||||
},
|
||||
pets: {
|
||||
required: false,
|
||||
serializedName: "pets",
|
||||
type: {
|
||||
name: "Sequence",
|
||||
element: {
|
||||
required: false,
|
||||
serializedName: "petElementType",
|
||||
type: {
|
||||
name: "Composite",
|
||||
polymorphicDiscriminator: "pet.type",
|
||||
uberParent: "Pet",
|
||||
className: "Pet"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
internalMappers.Product = {
|
||||
required: false,
|
||||
serializedName: "Product",
|
||||
type: {
|
||||
name: "Composite",
|
||||
className: "Product",
|
||||
modelProperties: {
|
||||
id: {
|
||||
serializedName: "id",
|
||||
constraints: {
|
||||
|
||||
},
|
||||
required: true,
|
||||
type: {
|
||||
name: "Number"
|
||||
}
|
||||
},
|
||||
name: {
|
||||
serializedName: "name",
|
||||
required: true,
|
||||
type: {
|
||||
name: "String"
|
||||
}
|
||||
},
|
||||
provisioningState: {
|
||||
serializedName: "properties.provisioningState",
|
||||
required: false,
|
||||
type: {
|
||||
name: "Enum",
|
||||
allowedValues: ["Creating", "Failed", "Succeeded"]
|
||||
}
|
||||
},
|
||||
tags: {
|
||||
serializedName: "tags",
|
||||
required: false,
|
||||
type: {
|
||||
name: "Dictionary",
|
||||
value: {
|
||||
type: {
|
||||
name: "String"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
dispatchTime: {
|
||||
serializedName: "dispatchTime",
|
||||
required: false,
|
||||
type: {
|
||||
name: "DateTime"
|
||||
}
|
||||
},
|
||||
invoiceInfo: {
|
||||
serializedName: "invoiceInfo",
|
||||
required: false,
|
||||
type: {
|
||||
name: "Composite",
|
||||
className: "Invoice"
|
||||
}
|
||||
},
|
||||
subProducts: {
|
||||
serializedName: "subProducts",
|
||||
required: false,
|
||||
type: {
|
||||
name: "Sequence",
|
||||
element: {
|
||||
type: {
|
||||
name: "Composite",
|
||||
className: "SubProduct"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
internalMappers.ProductListResult = {
|
||||
required: false,
|
||||
serializedName: "ProductListResult",
|
||||
type: {
|
||||
name: "Composite",
|
||||
className: "ProductListResult",
|
||||
modelProperties: {
|
||||
value: {
|
||||
serializedName: "",
|
||||
required: false,
|
||||
type: {
|
||||
name: "Sequence",
|
||||
element: {
|
||||
type: {
|
||||
name: "Composite",
|
||||
className: "Product"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
internalMappers.ProductListResultNextLink = {
|
||||
required: false,
|
||||
serializedName: "ProductListResultNextLink",
|
||||
type: {
|
||||
name: "Composite",
|
||||
className: "ProductListResultNextLink",
|
||||
modelProperties: {
|
||||
value: {
|
||||
serializedName: "",
|
||||
required: false,
|
||||
type: {
|
||||
name: "Sequence",
|
||||
element: {
|
||||
type: {
|
||||
name: "Composite",
|
||||
className: "Product"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
nextLink: {
|
||||
serializedName: "nextLink",
|
||||
required: false,
|
||||
type: {
|
||||
name: "String"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
internalMappers.SawShark = {
|
||||
required: false,
|
||||
serializedName: "sawshark",
|
||||
type: {
|
||||
name: "Composite",
|
||||
className: "Sawshark",
|
||||
modelProperties: {
|
||||
species: {
|
||||
required: false,
|
||||
serializedName: "species",
|
||||
type: {
|
||||
name: "String"
|
||||
}
|
||||
},
|
||||
length: {
|
||||
required: true,
|
||||
serializedName: "length",
|
||||
type: {
|
||||
name: "Number"
|
||||
}
|
||||
},
|
||||
siblings: {
|
||||
required: false,
|
||||
serializedName: "siblings",
|
||||
type: {
|
||||
name: "Sequence",
|
||||
element: {
|
||||
required: false,
|
||||
serializedName: "FishElementType",
|
||||
type: {
|
||||
name: "Composite",
|
||||
polymorphicDiscriminator: {
|
||||
serializedName: "fish.type",
|
||||
clientName: "fishtype"
|
||||
},
|
||||
uberParent: "Fish",
|
||||
className: "Fish"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
fishtype: {
|
||||
required: true,
|
||||
serializedName: "fish\\.type",
|
||||
type: {
|
||||
name: "String"
|
||||
}
|
||||
},
|
||||
age: {
|
||||
required: false,
|
||||
serializedName: "age",
|
||||
type: {
|
||||
name: "Number"
|
||||
}
|
||||
},
|
||||
birthday: {
|
||||
required: true,
|
||||
serializedName: "birthday",
|
||||
type: {
|
||||
name: "DateTime"
|
||||
}
|
||||
},
|
||||
picture: {
|
||||
required: false,
|
||||
serializedName: "picture",
|
||||
type: {
|
||||
name: "ByteArray"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
internalMappers.Shark = {
|
||||
required: false,
|
||||
serializedName: "shark",
|
||||
type: {
|
||||
name: "Composite",
|
||||
className: "Shark",
|
||||
modelProperties: {
|
||||
species: {
|
||||
required: false,
|
||||
serializedName: "species",
|
||||
type: {
|
||||
name: "String"
|
||||
}
|
||||
},
|
||||
length: {
|
||||
required: true,
|
||||
serializedName: "length",
|
||||
type: {
|
||||
name: "Number"
|
||||
}
|
||||
},
|
||||
siblings: {
|
||||
required: false,
|
||||
serializedName: "siblings",
|
||||
type: {
|
||||
name: "Sequence",
|
||||
element: {
|
||||
required: false,
|
||||
serializedName: "FishElementType",
|
||||
type: {
|
||||
name: "Composite",
|
||||
polymorphicDiscriminator: {
|
||||
serializedName: "fish.type",
|
||||
clientName: "fishtype"
|
||||
},
|
||||
uberParent: "Fish",
|
||||
className: "Fish"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
fishtype: {
|
||||
required: true,
|
||||
serializedName: "fish\\.type",
|
||||
type: {
|
||||
name: "String"
|
||||
}
|
||||
},
|
||||
age: {
|
||||
required: false,
|
||||
serializedName: "age",
|
||||
type: {
|
||||
name: "Number"
|
||||
}
|
||||
},
|
||||
birthday: {
|
||||
required: true,
|
||||
serializedName: "birthday",
|
||||
type: {
|
||||
name: "DateTime"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
internalMappers.SubProduct = {
|
||||
required: false,
|
||||
serializedName: "SubProduct",
|
||||
type: {
|
||||
name: "Composite",
|
||||
className: "SubProduct",
|
||||
modelProperties: {
|
||||
subId: {
|
||||
serializedName: "subId",
|
||||
required: true,
|
||||
type: {
|
||||
name: "Number"
|
||||
}
|
||||
},
|
||||
subName: {
|
||||
serializedName: "subName",
|
||||
required: true,
|
||||
type: {
|
||||
name: "String"
|
||||
}
|
||||
},
|
||||
provisioningState: {
|
||||
serializedName: "provisioningState",
|
||||
required: false,
|
||||
type: {
|
||||
name: "Enum",
|
||||
allowedValues: ["Creating", "Failed", "Succeeded"]
|
||||
}
|
||||
},
|
||||
makeTime: {
|
||||
serializedName: "makeTime",
|
||||
required: false,
|
||||
type: {
|
||||
name: "DateTime"
|
||||
}
|
||||
},
|
||||
invoiceInfo: {
|
||||
serializedName: "invoiceInfo",
|
||||
required: false,
|
||||
type: {
|
||||
name: "Composite",
|
||||
className: "Invoice"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
internalMappers.discriminators = {
|
||||
"Fish": internalMappers.Fish,
|
||||
"Fish.shark": internalMappers.Shark,
|
||||
"Fish.sawshark": internalMappers.SawShark,
|
||||
"Pet": internalMappers.Pet,
|
||||
"Pet.Cat": internalMappers.Cat,
|
||||
"Pet.Dog": internalMappers.Dog
|
||||
};
|
||||
|
||||
export const Mappers = internalMappers;
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for
|
||||
* license information.
|
||||
*
|
||||
* Code generated by Microsoft (R) AutoRest Code Generator 0.14.0.0
|
||||
* Changes may cause incorrect behavior and will be lost if the code is
|
||||
* regenerated.
|
||||
*/
|
||||
|
||||
/* jshint latedef:false */
|
||||
/* jshint forin:false */
|
||||
/* jshint noempty:false */
|
||||
|
||||
'use strict';
|
||||
|
||||
import * as msRest from '../../../../lib/msRest';
|
||||
import { Mappers } from './models/mappers';
|
||||
|
||||
/**
|
||||
* @class
|
||||
* Initializes a new instance of the TestClient class.
|
||||
* @constructor
|
||||
*
|
||||
* @param {string} [baseUri] - The base URI of the service.
|
||||
*
|
||||
* @param {object} [options] - The parameter options
|
||||
*
|
||||
* @param {Array} [options.filters] - Filters to be added to the request pipeline
|
||||
*
|
||||
* @param {object} [options.requestOptions] - Options for the underlying request object
|
||||
* {@link https://github.com/request/request#requestoptions-callback Options doc}
|
||||
*
|
||||
* @param {bool} [options.noRetryPolicy] - If set to true, turn off default retry policy
|
||||
*/
|
||||
|
||||
class TestClient extends msRest.ServiceClient {
|
||||
baseUri?: string;
|
||||
acceptLanguage?: string;
|
||||
models?: any;
|
||||
serializer: msRest.Serializer;
|
||||
constructor(baseUri: string, options?: msRest.ServiceClientOptions) {
|
||||
if (!options) options = {};
|
||||
super(undefined, options);
|
||||
this.baseUri = baseUri;
|
||||
if (!this.baseUri) {
|
||||
this.baseUri = 'https://management.azure.com';
|
||||
}
|
||||
|
||||
if (!this.acceptLanguage) {
|
||||
this.acceptLanguage = 'en-US';
|
||||
}
|
||||
this.serializer = new msRest.Serializer(Mappers);
|
||||
}
|
||||
}
|
||||
|
||||
export { TestClient };
|
|
@ -0,0 +1,43 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
|
||||
import * as assert from "assert";
|
||||
import { WebResource } from "../lib/webResource";
|
||||
import { HttpOperationResponse } from "../lib/httpOperationResponse";
|
||||
import { LogFilter } from "../lib/filters/logFilter";
|
||||
|
||||
import { Response } from "node-fetch";
|
||||
|
||||
describe("Log filter", () => {
|
||||
|
||||
it("should log messages when a logger object is provided", (done) => {
|
||||
const expected = `>> Request: {
|
||||
"headers": {},
|
||||
"rawResponse": false,
|
||||
"url": "https://foo.com",
|
||||
"method": "PUT",
|
||||
"body": {
|
||||
"a": 1
|
||||
}
|
||||
}
|
||||
>> Response status code: 200
|
||||
>> Body: null
|
||||
`;
|
||||
let output = "";
|
||||
const logger: Function = (message: string): void => { output += message + "\n"; };
|
||||
const lf = new LogFilter(logger);
|
||||
const req = new WebResource("https://foo.com", "PUT", { "a": 1 });
|
||||
const res = new Response();
|
||||
const opRes = new HttpOperationResponse(req, res as any, res.body as any);
|
||||
lf.after(opRes).then(() => {
|
||||
//console.dir(output, { depth: null });
|
||||
//console.log(">>>>>>>");
|
||||
//console.dir(expected);
|
||||
assert.deepEqual(output, expected);
|
||||
done();
|
||||
}).catch((err: Error) => {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,753 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
import * as assert from "assert";
|
||||
import * as moment from "moment";
|
||||
import * as msRest from "../lib/msRest";
|
||||
const should = require("should");
|
||||
|
||||
import { TestClient } from "./data/TestClient/lib/testClient";
|
||||
import { Mappers } from "./data/Testclient/lib/models/mappers";
|
||||
let Serializer = new msRest.Serializer({});
|
||||
let valid_uuid = "ceaafd1e-f936-429f-bbfc-82ee75dddc33";
|
||||
|
||||
describe("msrest", function () {
|
||||
describe("serializeObject", function () {
|
||||
it("should correctly serialize a Date Object", function (done) {
|
||||
let dateObj = new Date("2015-01-01");
|
||||
let dateISO = "2015-01-01T00:00:00.000Z";
|
||||
msRest.serializeObject(dateObj).should.equal(dateISO);
|
||||
done();
|
||||
});
|
||||
|
||||
it("should correctly serialize a Date object with max value", function (done) {
|
||||
let serializedDateString = msRest.serializeObject(new Date("9999-12-31T23:59:59-12:00"));
|
||||
serializedDateString.should.equal("+010000-01-01T11:59:59.000Z");
|
||||
done();
|
||||
});
|
||||
|
||||
it("should correctly serialize a Buffer Object", function (done) {
|
||||
let bufferObj = new Buffer("Javascript");
|
||||
let base64str = "SmF2YXNjcmlwdA==";
|
||||
msRest.serializeObject(bufferObj).should.equal(base64str);
|
||||
done();
|
||||
});
|
||||
|
||||
it("should correctly serialize Primitive types", function (done) {
|
||||
msRest.serializeObject(true).should.equal(true);
|
||||
msRest.serializeObject(false).should.equal(false);
|
||||
msRest.serializeObject("true").should.equal("true");
|
||||
msRest.serializeObject(1).should.equal(1);
|
||||
msRest.serializeObject(100.0123).should.equal(100.0123);
|
||||
assert.equal(msRest.serializeObject(null), null);
|
||||
done();
|
||||
});
|
||||
|
||||
it("should correctly serialize an empty array and an empty dictionary", function (done) {
|
||||
assert.deepEqual(msRest.serializeObject([]), []);
|
||||
assert.deepEqual(msRest.serializeObject({}), {});
|
||||
done();
|
||||
});
|
||||
|
||||
it("should correctly serialize a complex JSON object", function (done) {
|
||||
let o1: any = {
|
||||
"p1": "value1",
|
||||
"p2": "value2",
|
||||
"top-buf": new Buffer("top string", "utf-8"),
|
||||
"top-date": new Date("2014"),
|
||||
"top-dates": [new Date("1900"), new Date("1901")],
|
||||
"insider": {
|
||||
"insider-buf": new Buffer("insider string", "utf-8"),
|
||||
"insider-date": new Date("2015"),
|
||||
"insider-dates": [new Date("2100"), new Date("2101")],
|
||||
"insider-dictionary": {
|
||||
"k1": new Date("2015"),
|
||||
"k2": new Date("2016"),
|
||||
"k3": new Date("2017")
|
||||
},
|
||||
"top-complex": {
|
||||
"id": 1,
|
||||
"name": "Joey",
|
||||
"age": 23.36,
|
||||
"male": true,
|
||||
"birthday": "1992-01-01T00:00:00.000Z",
|
||||
"anniversary": new Date("2013-12-08"),
|
||||
"memory": new Buffer("Yadadadada")
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let o2: any = {
|
||||
p1: "value1",
|
||||
p2: "value2",
|
||||
"top-buf": "dG9wIHN0cmluZw==",
|
||||
"top-date": "2014-01-01T00:00:00.000Z",
|
||||
"top-dates": [
|
||||
"1900-01-01T00:00:00.000Z",
|
||||
"1901-01-01T00:00:00.000Z"
|
||||
],
|
||||
insider: {
|
||||
"insider-buf": "aW5zaWRlciBzdHJpbmc=",
|
||||
"insider-date": "2015-01-01T00:00:00.000Z",
|
||||
"insider-dates": [
|
||||
"2100-01-01T00:00:00.000Z",
|
||||
"2101-01-01T00:00:00.000Z"
|
||||
],
|
||||
"insider-dictionary": {
|
||||
k1: "2015-01-01T00:00:00.000Z",
|
||||
k2: "2016-01-01T00:00:00.000Z",
|
||||
k3: "2017-01-01T00:00:00.000Z"
|
||||
},
|
||||
"top-complex": {
|
||||
id: 1,
|
||||
name: "Joey",
|
||||
age: 23.36,
|
||||
male: true,
|
||||
birthday: "1992-01-01T00:00:00.000Z",
|
||||
anniversary: "2013-12-08T00:00:00.000Z",
|
||||
memory: "WWFkYWRhZGFkYQ=="
|
||||
}
|
||||
}
|
||||
};
|
||||
assert.deepEqual(msRest.serializeObject(o1), o2);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
describe("serialize", function () {
|
||||
let invalid_uuid = "abcd-efgd90-90890jkh";
|
||||
it("should correctly serialize a string", function (done) {
|
||||
let mapper: msRest.Mapper = { type: { name: "String" }, required: false, serializedName: "string" };
|
||||
let serializedObject = Serializer.serialize(mapper, "foo", "stringBody");
|
||||
serializedObject.should.equal("foo");
|
||||
done();
|
||||
});
|
||||
it("should correctly serialize a uuid", function (done) {
|
||||
let mapper: msRest.Mapper = { type: { name: "Uuid" }, required: false, serializedName: "Uuid" };
|
||||
let serializedObject = Serializer.serialize(mapper, valid_uuid, "uuidBody");
|
||||
serializedObject.should.equal(valid_uuid);
|
||||
done();
|
||||
});
|
||||
it("should throw an error if the value is not a valid Uuid", function (done) {
|
||||
let mapper: msRest.Mapper = { type: { name: "Uuid" }, required: false, serializedName: "Uuid" };
|
||||
try {
|
||||
Serializer.serialize(mapper, invalid_uuid, "uuidBody");
|
||||
} catch (error) {
|
||||
error.message.should.match(/.*with value.*must be of type string and a valid uuid/ig);
|
||||
done();
|
||||
}
|
||||
});
|
||||
it("should correctly serialize a number", function (done) {
|
||||
let mapper: msRest.Mapper = { type: { name: "Number" }, required: false, serializedName: "Number" };
|
||||
let serializedObject = Serializer.serialize(mapper, 1.506, "stringBody");
|
||||
serializedObject.should.equal(1.506);
|
||||
done();
|
||||
});
|
||||
it("should correctly serialize a boolean", function (done) {
|
||||
let mapper: msRest.Mapper = { type: { name: "Boolean" }, required: false, serializedName: "Boolean" };
|
||||
let serializedObject = Serializer.serialize(mapper, false, "stringBody");
|
||||
serializedObject.should.equal(false);
|
||||
done();
|
||||
});
|
||||
it("should correctly serialize an Enum", function (done) {
|
||||
let mapper: msRest.EnumMapper = { type: { name: "Enum", allowedValues: [1, 2, 3, 4] }, required: false, serializedName: "Enum" };
|
||||
let serializedObject = Serializer.serialize(mapper, 1, "enumBody");
|
||||
serializedObject.should.equal(1);
|
||||
done();
|
||||
});
|
||||
it("should throw an error if the value is not valid for an Enum", function (done) {
|
||||
let mapper: msRest.EnumMapper = { type: { name: "Enum", allowedValues: [1, 2, 3, 4] }, required: false, serializedName: "Enum" };
|
||||
try {
|
||||
Serializer.serialize(mapper, 6, "enumBody");
|
||||
} catch (error) {
|
||||
error.message.should.match(/6 is not a valid value for enumBody\. The valid values are: \[1,2,3,4\]/ig);
|
||||
done();
|
||||
}
|
||||
});
|
||||
|
||||
it("should correctly serialize a Buffer Object", function (done) {
|
||||
let mapper: msRest.Mapper = { type: { name: "ByteArray" }, required: false, serializedName: "ByteArray" };
|
||||
let bufferObj = new Buffer("Javascript");
|
||||
let base64str = "SmF2YXNjcmlwdA==";
|
||||
let serializedObject = Serializer.serialize(mapper, bufferObj, "stringBody");
|
||||
serializedObject.should.equal(base64str);
|
||||
done();
|
||||
});
|
||||
|
||||
it("should correctly serialize a Date Object", function (done) {
|
||||
let dateObj = new Date("2015-01-01");
|
||||
let dateISO = "2015-01-01";
|
||||
let mapper: msRest.Mapper = { type: { name: "Date" }, required: false, serializedName: "Date" };
|
||||
Serializer.serialize(mapper, dateObj, "dateObj").should.equal(dateISO);
|
||||
done();
|
||||
});
|
||||
it("should correctly serialize a Date object with max value", function (done) {
|
||||
let mapper: msRest.Mapper = { type: { name: "DateTime" }, required: false, serializedName: "DateTime" };
|
||||
let serializedDateString = Serializer.serialize(mapper, new Date("9999-12-31T23:59:59-12:00"), "dateTimeObj");
|
||||
should.equal(serializedDateString, "+010000-01-01T11:59:59.000Z");
|
||||
done();
|
||||
});
|
||||
it("should correctly serialize a Date object with max value and format UnixTime", function (done) {
|
||||
let mapper: msRest.Mapper = { type: { name: "UnixTime" }, required: false, serializedName: "UnixTime" };
|
||||
let serializedDate = Serializer.serialize(mapper, new Date("9999-12-31T23:59:59-12:00"), "dateTimeObj");
|
||||
serializedDate.should.equal(253402343999);
|
||||
done();
|
||||
});
|
||||
it("should correctly serialize a string in DateTimeRfc1123", function (done) {
|
||||
let mapper: msRest.Mapper = { type: { name: "DateTimeRfc1123" }, required: false, serializedName: "DateTimeRfc1123" };
|
||||
let rfc = new Date("Mon, 01 Jan 0001 00:00:00 GMT");
|
||||
let serializedDateString = Serializer.serialize(mapper, rfc, "dateTimeObj");
|
||||
serializedDateString.should.equal("Mon, 01 Jan 2001 00:00:00 GMT");
|
||||
done();
|
||||
});
|
||||
it("should correctly serialize a duration object", function (done) {
|
||||
let mapper: msRest.Mapper = { type: { name: "TimeSpan" }, required: false, serializedName: "TimeSpan" };
|
||||
let duration = moment.duration({ days: 123, hours: 22, minutes: 14, seconds: 12, milliseconds: 11 });
|
||||
let serializedDateString = Serializer.serialize(mapper, duration, "dateTimeObj");
|
||||
serializedDateString.should.equal("P123DT22H14M12.010999999998603S");
|
||||
done();
|
||||
});
|
||||
|
||||
it("should correctly serialize an array of primitives", function (done) {
|
||||
let mapper: msRest.SequenceMapper = {
|
||||
required: false,
|
||||
serializedName: "Sequence",
|
||||
type: {
|
||||
name: "Sequence",
|
||||
element: {
|
||||
type: { name: "String" },
|
||||
required: true,
|
||||
serializedName: "sequenceElement"
|
||||
}
|
||||
}
|
||||
};
|
||||
let array = ["One", "Two", "three"];
|
||||
let serializedArray = Serializer.serialize(mapper, array, "arrayObj");
|
||||
assert.deepEqual(array, serializedArray);
|
||||
done();
|
||||
});
|
||||
|
||||
it("should correctly serialize an array of array of primitives", function (done) {
|
||||
let mapper: msRest.SequenceMapper = {
|
||||
required: false,
|
||||
serializedName: "Sequence",
|
||||
type: {
|
||||
name: "Sequence",
|
||||
element: {
|
||||
required: true,
|
||||
serializedName: "sequenceElement",
|
||||
type: {
|
||||
name: "Sequence",
|
||||
element: {
|
||||
required: true,
|
||||
serializedName: "sequenceElement",
|
||||
type: {
|
||||
name: "Number"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
let array = [[1], [2], [1, 2, 3]];
|
||||
let serializedArray = Serializer.serialize(mapper, array, "arrayObj");
|
||||
assert.deepEqual(array, serializedArray);
|
||||
done();
|
||||
});
|
||||
|
||||
it("should correctly serialize an array of dictionary of primitives", function (done) {
|
||||
let mapper: msRest.SequenceMapper = {
|
||||
required: false,
|
||||
serializedName: "Sequence",
|
||||
type: {
|
||||
name: "Sequence",
|
||||
element: {
|
||||
required: true,
|
||||
serializedName: "sequenceElement",
|
||||
type: {
|
||||
name: "Dictionary",
|
||||
value: {
|
||||
required: true,
|
||||
serializedName: "valueElement",
|
||||
type: {
|
||||
name: "Boolean"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
let array = [{ 1: true }, { 2: false }, { 1: true, 2: false, 3: true }];
|
||||
let serializedArray = Serializer.serialize(mapper, array, "arrayObj");
|
||||
assert.deepEqual(array, serializedArray);
|
||||
done();
|
||||
});
|
||||
|
||||
it("should correctly serialize a dictionary of primitives", function (done) {
|
||||
let mapper: msRest.DictionaryMapper = {
|
||||
required: false,
|
||||
serializedName: "Dictionary",
|
||||
type: {
|
||||
name: "Dictionary",
|
||||
value: {
|
||||
required: true,
|
||||
serializedName: "valueElement",
|
||||
type: {
|
||||
name: "String"
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
let dict = { 1: "One", 2: "Two", 3: "three" };
|
||||
let serializedDictionary = Serializer.serialize(mapper, dict, "dictObj");
|
||||
assert.deepEqual(dict, serializedDictionary);
|
||||
done();
|
||||
});
|
||||
|
||||
it("should correctly serialize a dictionary of array of primitives", function (done) {
|
||||
let mapper: msRest.DictionaryMapper = {
|
||||
required: false,
|
||||
serializedName: "Dictionary",
|
||||
type: {
|
||||
name: "Dictionary",
|
||||
value: {
|
||||
required: true,
|
||||
serializedName: "valueElement",
|
||||
type: {
|
||||
name: "Sequence",
|
||||
element: {
|
||||
required: true,
|
||||
serializedName: "sequenceElement",
|
||||
type: {
|
||||
name: "Number"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
let dict = { "One": [1], "Two": [1, 2], "three": [1, 2, 3] };
|
||||
let serializedDictionary = Serializer.serialize(mapper, dict, "dictObj");
|
||||
assert.deepEqual(dict, serializedDictionary);
|
||||
done();
|
||||
});
|
||||
|
||||
it("should correctly serialize a dictionary of dictionary of primitives", function (done) {
|
||||
let mapper: msRest.DictionaryMapper = {
|
||||
required: false,
|
||||
serializedName: "Dictionary",
|
||||
type: {
|
||||
name: "Dictionary",
|
||||
value: {
|
||||
required: true,
|
||||
serializedName: "valueElement",
|
||||
type: {
|
||||
name: "Dictionary",
|
||||
value: {
|
||||
required: true,
|
||||
serializedName: "valueElement",
|
||||
type: {
|
||||
name: "Boolean"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
let dict = { 1: { "One": true }, 2: { "Two": false }, 3: { "three": true } };
|
||||
let serializedDictionary = Serializer.serialize(mapper, dict, "dictObj");
|
||||
assert.deepEqual(dict, serializedDictionary);
|
||||
done();
|
||||
});
|
||||
|
||||
it("should correctly serialize a composite type", function (done) {
|
||||
let client = new TestClient("http://localhost:9090");
|
||||
let mapper = Mappers.Product;
|
||||
let productObj = {
|
||||
id: 101,
|
||||
name: "TestProduct",
|
||||
provisioningState: "Succeeded",
|
||||
tags: {
|
||||
tag1: "value1",
|
||||
tag2: "value2"
|
||||
},
|
||||
dispatchTime: new Date("2015-01-01T12:35:36.009Z"),
|
||||
invoiceInfo: {
|
||||
invId: 1002,
|
||||
invDate: "2015-12-25",
|
||||
invProducts: [
|
||||
{
|
||||
"Product1": {
|
||||
id: 101,
|
||||
name: "TestProduct"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Product2": {
|
||||
id: 104,
|
||||
name: "TestProduct1"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
subProducts: [
|
||||
{
|
||||
subId: 102,
|
||||
subName: "SubProduct1",
|
||||
makeTime: new Date("2015-12-21T01:01:01"),
|
||||
invoiceInfo: {
|
||||
invId: 1002,
|
||||
invDate: "2015-12-25"
|
||||
}
|
||||
},
|
||||
{
|
||||
subId: 103,
|
||||
subName: "SubProduct2",
|
||||
makeTime: new Date("2015-12-21T01:01:01"),
|
||||
invoiceInfo: {
|
||||
invId: 1003,
|
||||
invDate: "2015-12-25"
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
let serializedProduct = client.serializer.serialize(mapper, productObj, "productObject");
|
||||
for (let prop in serializedProduct) {
|
||||
if (prop === "properties") {
|
||||
serializedProduct[prop].provisioningState.should.equal(productObj.provisioningState);
|
||||
} else if (prop === "id") {
|
||||
serializedProduct[prop].should.equal(productObj.id);
|
||||
} else if (prop === "name") {
|
||||
serializedProduct[prop].should.equal(productObj.name);
|
||||
} else if (prop === "tags") {
|
||||
JSON.stringify(serializedProduct[prop]).should.equal(JSON.stringify(productObj.tags));
|
||||
} else if (prop === "dispatchTime") {
|
||||
JSON.stringify(serializedProduct[prop]).should.equal(JSON.stringify(productObj.dispatchTime));
|
||||
} else if (prop === "invoiceInfo") {
|
||||
(JSON.stringify(serializedProduct[prop]).length - JSON.stringify(productObj.invoiceInfo).length).should.equal(4);
|
||||
} else if (prop === "subProducts") {
|
||||
(JSON.stringify(serializedProduct[prop]).length - JSON.stringify(productObj.subProducts).length).should.equal(8);
|
||||
}
|
||||
}
|
||||
done();
|
||||
});
|
||||
|
||||
it("should correctly serialize object version of polymorphic discriminator", function (done) {
|
||||
let client = new TestClient("http://localhost:9090");
|
||||
let mapper = Mappers.SawShark;
|
||||
let sawshark = {
|
||||
"fishtype": "sawshark",
|
||||
"age": 22,
|
||||
"birthday": new Date("2012-01-05T01:00:00Z"),
|
||||
"species": "king",
|
||||
"length": 1.0,
|
||||
"picture": new Buffer([255, 255, 255, 255, 254]),
|
||||
"siblings": [
|
||||
{
|
||||
"fishtype": "shark",
|
||||
"age": 6,
|
||||
"birthday": new Date("2012-01-05T01:00:00Z"),
|
||||
"length": 20.0,
|
||||
"species": "predator"
|
||||
},
|
||||
{
|
||||
"fishtype": "sawshark",
|
||||
"age": 105,
|
||||
"birthday": new Date("1900-01-05T01:00:00Z"),
|
||||
"length": 10.0,
|
||||
"picture": new Buffer([255, 255, 255, 255, 254]),
|
||||
"species": "dangerous"
|
||||
}
|
||||
]
|
||||
};
|
||||
let serializedSawshark = client.serializer.serialize(mapper, sawshark, "result");
|
||||
serializedSawshark.age.should.equal(22);
|
||||
serializedSawshark["fish.type"].should.equal("sawshark");
|
||||
serializedSawshark.siblings.length.should.equal(2);
|
||||
serializedSawshark.siblings[0]["fish.type"].should.equal("shark");
|
||||
serializedSawshark.siblings[0].age.should.equal(6);
|
||||
serializedSawshark.siblings[0].birthday.should.equal(new Date("2012-01-05T01:00:00Z").toISOString());
|
||||
serializedSawshark.siblings[1]["fish.type"].should.equal("sawshark");
|
||||
serializedSawshark.siblings[1].age.should.equal(105);
|
||||
serializedSawshark.siblings[1].birthday.should.equal(new Date("1900-01-05T01:00:00Z").toISOString());
|
||||
serializedSawshark.siblings[1].picture.should.equal("//////4=");
|
||||
serializedSawshark.picture.should.equal("//////4=");
|
||||
done();
|
||||
});
|
||||
|
||||
it("should correctly serialize string version of polymorphic discriminator", function (done) {
|
||||
let client = new TestClient("http://localhost:9090");
|
||||
let mapper = Mappers.PetGallery;
|
||||
let petgallery = {
|
||||
"id": 1,
|
||||
"name": "Fav pet gallery",
|
||||
"pets": [
|
||||
{
|
||||
"id": 2,
|
||||
"name": "moti",
|
||||
"food": "buiscuit",
|
||||
"pet.type": "Dog",
|
||||
"pettype": "Dog"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"name": "billa",
|
||||
"color": "red",
|
||||
"pet.type": "Cat",
|
||||
"pettype": "Cat" // In string version the user has to pass the actual property with dot and the normalized one.
|
||||
}
|
||||
]
|
||||
};
|
||||
let serializedPetGallery = client.serializer.serialize(mapper, petgallery, "result");
|
||||
serializedPetGallery.id.should.equal(1);
|
||||
serializedPetGallery.name.should.equal("Fav pet gallery");
|
||||
serializedPetGallery.pets.length.should.equal(2);
|
||||
serializedPetGallery.pets[0]["pet.type"].should.equal("Dog");
|
||||
serializedPetGallery.pets[0].id.should.equal(2);
|
||||
serializedPetGallery.pets[0].name.should.equal("moti");
|
||||
serializedPetGallery.pets[0].food.should.equal("buiscuit");
|
||||
serializedPetGallery.pets[1]["pet.type"].should.equal("Cat");
|
||||
serializedPetGallery.pets[1].id.should.equal(3);
|
||||
serializedPetGallery.pets[1].name.should.equal("billa");
|
||||
serializedPetGallery.pets[1].color.should.equal("red");
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
describe("deserialize", function () {
|
||||
it("should correctly deserialize a uuid", function (done) {
|
||||
let mapper: msRest.Mapper = { type: { name: "Uuid" }, required: false, serializedName: "Uuid" };
|
||||
let serializedObject = Serializer.deserialize(mapper, valid_uuid, "uuidBody");
|
||||
serializedObject.should.equal(valid_uuid);
|
||||
done();
|
||||
});
|
||||
it("should correctly deserialize a composite type", function (done) {
|
||||
let client = new TestClient("http://localhost:9090");
|
||||
let mapper = Mappers.Product;
|
||||
let responseBody = {
|
||||
id: 101,
|
||||
name: "TestProduct",
|
||||
properties: {
|
||||
provisioningState: "Succeeded"
|
||||
},
|
||||
tags: {
|
||||
tag1: "value1",
|
||||
tag2: "value2"
|
||||
},
|
||||
dispatchTime: new Date("2015-01-01T12:35:36.009Z"),
|
||||
invoiceInfo: {
|
||||
invoiceId: 1002,
|
||||
invDate: "2015-12-25",
|
||||
invProducts: [
|
||||
{
|
||||
"Product1": {
|
||||
id: 101,
|
||||
name: "TestProduct"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Product2": {
|
||||
id: 104,
|
||||
name: "TestProduct1"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
subProducts: [
|
||||
{
|
||||
subId: 102,
|
||||
subName: "SubProduct1",
|
||||
makeTime: new Date("2015-12-21T01:01:01"),
|
||||
invoiceInfo: {
|
||||
invoiceId: 1002,
|
||||
invDate: "2015-12-25"
|
||||
}
|
||||
},
|
||||
{
|
||||
subId: 103,
|
||||
subName: "SubProduct2",
|
||||
makeTime: new Date("2015-12-21T01:01:01"),
|
||||
invoiceInfo: {
|
||||
invoiceId: 1003,
|
||||
invDate: "2015-12-25"
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
let deserializedProduct = client.serializer.deserialize(mapper, responseBody, "responseBody");
|
||||
for (let prop in deserializedProduct) {
|
||||
if (prop === "provisioningState") {
|
||||
deserializedProduct.provisioningState.should.equal(responseBody.properties.provisioningState);
|
||||
} else if (prop === "id") {
|
||||
deserializedProduct[prop].should.equal(responseBody.id);
|
||||
} else if (prop === "name") {
|
||||
deserializedProduct[prop].should.equal(responseBody.name);
|
||||
} else if (prop === "tags") {
|
||||
JSON.stringify(deserializedProduct[prop]).should.equal(JSON.stringify(responseBody.tags));
|
||||
} else if (prop === "dispatchTime") {
|
||||
JSON.stringify(deserializedProduct[prop]).should.equal(JSON.stringify(responseBody.dispatchTime));
|
||||
} else if (prop === "invoiceInfo") {
|
||||
(JSON.stringify(deserializedProduct[prop]).length - JSON.stringify(responseBody.invoiceInfo).length).should.equal(10);
|
||||
} else if (prop === "subProducts") {
|
||||
(JSON.stringify(deserializedProduct[prop]).length - JSON.stringify(responseBody.subProducts).length).should.equal(20);
|
||||
}
|
||||
}
|
||||
done();
|
||||
});
|
||||
|
||||
it("should correctly deserialize a pageable type without nextLink", function (done) {
|
||||
let client = new TestClient("http://localhost:9090");
|
||||
let mapper = Mappers.ProductListResult;
|
||||
let responseBody = {
|
||||
value: [
|
||||
{
|
||||
id: 101,
|
||||
name: "TestProduct",
|
||||
properties: {
|
||||
provisioningState: "Succeeded"
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 104,
|
||||
name: "TestProduct1",
|
||||
properties: {
|
||||
provisioningState: "Failed"
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
let deserializedProduct = client.serializer.deserialize(mapper, responseBody, "responseBody");
|
||||
(Array.isArray(deserializedProduct)).should.be.true;
|
||||
deserializedProduct.length.should.equal(2);
|
||||
for (let i = 0; i < deserializedProduct.length; i++) {
|
||||
if (i === 0) {
|
||||
deserializedProduct[i].id.should.equal(101);
|
||||
deserializedProduct[i].name.should.equal("TestProduct");
|
||||
deserializedProduct[i].provisioningState.should.equal("Succeeded");
|
||||
} else if (i === 1) {
|
||||
deserializedProduct[i].id.should.equal(104);
|
||||
deserializedProduct[i].name.should.equal("TestProduct1");
|
||||
deserializedProduct[i].provisioningState.should.equal("Failed");
|
||||
}
|
||||
}
|
||||
done();
|
||||
});
|
||||
|
||||
it("should correctly deserialize a pageable type with nextLink", function (done) {
|
||||
let client = new TestClient("http://localhost:9090");
|
||||
let mapper = Mappers.ProductListResultNextLink;
|
||||
let responseBody = {
|
||||
value: [
|
||||
{
|
||||
id: 101,
|
||||
name: "TestProduct",
|
||||
properties: {
|
||||
provisioningState: "Succeeded"
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 104,
|
||||
name: "TestProduct1",
|
||||
properties: {
|
||||
provisioningState: "Failed"
|
||||
}
|
||||
}
|
||||
],
|
||||
nextLink: "https://helloworld.com"
|
||||
};
|
||||
let deserializedProduct = client.serializer.deserialize(mapper, responseBody, "responseBody");
|
||||
(Array.isArray(deserializedProduct)).should.be.true;
|
||||
deserializedProduct.length.should.equal(2);
|
||||
deserializedProduct.nextLink.should.equal("https://helloworld.com");
|
||||
for (let i = 0; i < deserializedProduct.length; i++) {
|
||||
if (i === 0) {
|
||||
deserializedProduct[i].id.should.equal(101);
|
||||
deserializedProduct[i].name.should.equal("TestProduct");
|
||||
deserializedProduct[i].provisioningState.should.equal("Succeeded");
|
||||
} else if (i === 1) {
|
||||
deserializedProduct[i].id.should.equal(104);
|
||||
deserializedProduct[i].name.should.equal("TestProduct1");
|
||||
deserializedProduct[i].provisioningState.should.equal("Failed");
|
||||
}
|
||||
}
|
||||
done();
|
||||
});
|
||||
|
||||
it("should correctly deserialize object version of polymorphic discriminator", function (done) {
|
||||
let client = new TestClient("http://localhost:9090");
|
||||
let mapper = Mappers.Fish;
|
||||
let responseBody = {
|
||||
"fish.type": "sawshark",
|
||||
"age": 22,
|
||||
"birthday": new Date("2012-01-05T01:00:00Z").toISOString(),
|
||||
"species": "king",
|
||||
"length": 1.0,
|
||||
"picture": new Buffer([255, 255, 255, 255, 254]).toString(),
|
||||
"siblings": [
|
||||
{
|
||||
"fish.type": "shark",
|
||||
"age": 6,
|
||||
"birthday": new Date("2012-01-05T01:00:00Z"),
|
||||
"length": 20.0,
|
||||
"species": "predator"
|
||||
},
|
||||
{
|
||||
"fish.type": "sawshark",
|
||||
"age": 105,
|
||||
"birthday": new Date("1900-01-05T01:00:00Z").toISOString(),
|
||||
"length": 10.0,
|
||||
"picture": new Buffer([255, 255, 255, 255, 254]).toString(),
|
||||
"species": "dangerous"
|
||||
}
|
||||
]
|
||||
};
|
||||
let deserializedSawshark = client.serializer.deserialize(mapper, responseBody, "responseBody");
|
||||
deserializedSawshark.age.should.equal(22);
|
||||
deserializedSawshark.fishtype.should.equal("sawshark");
|
||||
deserializedSawshark.siblings.length.should.equal(2);
|
||||
deserializedSawshark.siblings[0].fishtype.should.equal("shark");
|
||||
deserializedSawshark.siblings[0].age.should.equal(6);
|
||||
deserializedSawshark.siblings[0].birthday.toISOString().should.equal("2012-01-05T01:00:00.000Z");
|
||||
deserializedSawshark.siblings[1].fishtype.should.equal("sawshark");
|
||||
deserializedSawshark.siblings[1].age.should.equal(105);
|
||||
deserializedSawshark.siblings[1].birthday.toISOString().should.equal("1900-01-05T01:00:00.000Z");
|
||||
done();
|
||||
});
|
||||
|
||||
it("should correctly deserialize string version of polymorphic discriminator", function (done) {
|
||||
let client = new TestClient("http://localhost:9090");
|
||||
let mapper = Mappers.PetGallery;
|
||||
let petgallery = {
|
||||
"id": 1,
|
||||
"name": "Fav pet gallery",
|
||||
"pets": [
|
||||
{
|
||||
"id": 2,
|
||||
"name": "moti",
|
||||
"food": "buiscuit",
|
||||
"pet.type": "Dog",
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"name": "billa",
|
||||
"color": "red",
|
||||
"pet.type": "Cat",
|
||||
}
|
||||
]
|
||||
};
|
||||
let deserializedPetGallery = client.serializer.deserialize(mapper, petgallery, "result");
|
||||
deserializedPetGallery.id.should.equal(1);
|
||||
deserializedPetGallery.name.should.equal("Fav pet gallery");
|
||||
deserializedPetGallery.pets.length.should.equal(2);
|
||||
deserializedPetGallery.pets[0]["pettype"].should.equal("Dog");
|
||||
deserializedPetGallery.pets[0].id.should.equal(2);
|
||||
deserializedPetGallery.pets[0].name.should.equal("moti");
|
||||
deserializedPetGallery.pets[0].food.should.equal("buiscuit");
|
||||
deserializedPetGallery.pets[1]["pettype"].should.equal("Cat");
|
||||
deserializedPetGallery.pets[1].id.should.equal(3);
|
||||
deserializedPetGallery.pets[1].name.should.equal("billa");
|
||||
deserializedPetGallery.pets[1].color.should.equal("red");
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,68 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
import * as assert from "assert";
|
||||
import { WebResource } from "../lib/webResource";
|
||||
import { MsRestUserAgentFilter } from "../lib/filters/msRestUserAgentFilter";
|
||||
import { Constants } from "../lib/util/constants";
|
||||
|
||||
const should = require("should");
|
||||
const userAgentHeader = Constants.HeaderConstants.USER_AGENT;
|
||||
|
||||
describe("ms-rest user agent filter", () => {
|
||||
|
||||
it("should construct user agent header when supplied empty array", (done) => {
|
||||
const userAgentArray: Array<string> = [];
|
||||
const userAgentFilter = new MsRestUserAgentFilter(userAgentArray);
|
||||
const resource = new WebResource();
|
||||
resource.headers = {};
|
||||
userAgentFilter.before(resource).then((resource) => {
|
||||
should.ok(resource);
|
||||
resource.headers[userAgentHeader].should.containEql("Node");
|
||||
resource.headers[userAgentHeader].should.containEql("Azure-SDK-For-Node");
|
||||
done();
|
||||
}).catch((err) => { done(err); });
|
||||
});
|
||||
|
||||
it("should not modify user agent header if already present", (done) => {
|
||||
const genericRuntime = "ms-rest";
|
||||
const azureRuntime = "ms-rest-azure";
|
||||
const azureSDK = "Azure-SDK-For-Node";
|
||||
const userAgentArray = [`${genericRuntime}/v1.0.0`, `${azureRuntime}/v1.0.0`];
|
||||
const userAgentFilter = new MsRestUserAgentFilter(userAgentArray);
|
||||
const customUA = "my custom user agent";
|
||||
const resource = new WebResource();
|
||||
resource.headers = {};
|
||||
resource.headers[userAgentHeader] = customUA;
|
||||
userAgentFilter.before(resource).then((resource) => {
|
||||
should.ok(resource);
|
||||
const actualUA = resource.headers[userAgentHeader];
|
||||
actualUA.should.not.containEql("Node");
|
||||
actualUA.should.not.containEql(azureSDK);
|
||||
actualUA.should.not.containEql(azureRuntime);
|
||||
actualUA.should.containEql(customUA);
|
||||
done();
|
||||
}).catch((err) => { done(err); });
|
||||
});
|
||||
|
||||
it("should insert azure-sdk-for-node at right position", (done) => {
|
||||
const genericRuntime = "ms-rest";
|
||||
const azureRuntime = "ms-rest-azure";
|
||||
const azureSDK = "Azure-SDK-For-Node";
|
||||
const userAgentArray = [`${genericRuntime}/v1.0.0`, `${azureRuntime}/v1.0.0`];
|
||||
const userAgentFilter = new MsRestUserAgentFilter(userAgentArray);
|
||||
const resource = new WebResource();
|
||||
resource.headers = {};
|
||||
userAgentFilter.before(resource).then((resource) => {
|
||||
should.ok(resource);
|
||||
const deconstructedUserAgent = resource.headers[userAgentHeader].split(" ");
|
||||
should.ok(deconstructedUserAgent);
|
||||
const indexOfAzureRuntime = deconstructedUserAgent.findIndex((e: string) => e.startsWith(azureRuntime));
|
||||
assert.notEqual(indexOfAzureRuntime, -1, `did not find ${azureRuntime} in user agent`);
|
||||
const indexOfAzureSDK = deconstructedUserAgent.indexOf(azureSDK);
|
||||
assert.notEqual(indexOfAzureSDK, -1, `did not find ${azureSDK} in user agent`);
|
||||
assert.equal(indexOfAzureSDK, 1 + indexOfAzureRuntime, `${azureSDK} is not in the right place in user agent string`);
|
||||
done();
|
||||
}).catch((err) => { done(err); });
|
||||
});
|
||||
});
|
|
@ -0,0 +1,40 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"alwaysStrict": true,
|
||||
"module": "commonjs",
|
||||
"noImplicitAny": true,
|
||||
"preserveConstEnums": true,
|
||||
"sourceMap": true,
|
||||
"newLine": "LF",
|
||||
"target": "es6",
|
||||
"moduleResolution": "node",
|
||||
"noImplicitReturns": true,
|
||||
"noImplicitThis": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"outDir": "dist",
|
||||
"allowJs": false,
|
||||
"strict": true,
|
||||
"strictNullChecks": true,
|
||||
"declaration": true,
|
||||
"declarationDir": "./typings",
|
||||
"lib": [
|
||||
"dom",
|
||||
"dom.iterable",
|
||||
"es5",
|
||||
"es6",
|
||||
"es7",
|
||||
"esnext",
|
||||
"esnext.asynciterable",
|
||||
"es2015.iterable"
|
||||
]
|
||||
},
|
||||
"compileOnSave": true,
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
],
|
||||
"include": [
|
||||
"./lib/**/*.ts",
|
||||
"./test/**/*.ts"
|
||||
]
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
{
|
||||
"rules": {
|
||||
"class-name": true,
|
||||
"comment-format": [true,
|
||||
"check-space"
|
||||
],
|
||||
"indent": [true,
|
||||
"spaces"
|
||||
],
|
||||
"linebreak-style": [true, "LF"],
|
||||
"one-line": [true,
|
||||
"check-open-brace",
|
||||
"check-whitespace"
|
||||
],
|
||||
"no-var-keyword": true,
|
||||
"quotemark": [true,
|
||||
"double",
|
||||
"avoid-escape"
|
||||
],
|
||||
"semicolon": [true, "always", "ignore-bound-class-methods"],
|
||||
"whitespace": [true,
|
||||
"check-branch",
|
||||
"check-decl",
|
||||
"check-operator",
|
||||
"check-module",
|
||||
"check-separator",
|
||||
"check-type"
|
||||
],
|
||||
"typedef-whitespace": [
|
||||
true,
|
||||
{
|
||||
"call-signature": "nospace",
|
||||
"index-signature": "nospace",
|
||||
"parameter": "nospace",
|
||||
"property-declaration": "nospace",
|
||||
"variable-declaration": "nospace"
|
||||
},
|
||||
{
|
||||
"call-signature": "onespace",
|
||||
"index-signature": "onespace",
|
||||
"parameter": "onespace",
|
||||
"property-declaration": "onespace",
|
||||
"variable-declaration": "onespace"
|
||||
}
|
||||
],
|
||||
"no-internal-module": true,
|
||||
"no-trailing-whitespace": true,
|
||||
"no-inferrable-types": [true],
|
||||
"no-null-keyword": true,
|
||||
"prefer-const": true,
|
||||
"no-switch-case-fall-through": true,
|
||||
"triple-equals": true,
|
||||
"jsdoc-format": true
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
import { WebResource } from "../webResource";
|
||||
import { ServiceClientCredentials } from "./serviceClientCredentials";
|
||||
/**
|
||||
* Creates a new BasicAuthenticationCredentials object.
|
||||
*
|
||||
* @constructor
|
||||
* @param {string} userName User name.
|
||||
* @param {string} password Password.
|
||||
* @param {string} [authorizationScheme] The authorization scheme.
|
||||
*/
|
||||
export declare class BasicAuthenticationCredentials implements ServiceClientCredentials {
|
||||
userName: string;
|
||||
password: string;
|
||||
authorizationScheme: string;
|
||||
constructor(userName: string, password: string, authorizationScheme?: string);
|
||||
/**
|
||||
* Signs a request with the Authentication header.
|
||||
*
|
||||
* @param {WebResource} The WebResource to be signed.
|
||||
* @returns {Promise<WebResource>} - The signed request object.
|
||||
*/
|
||||
signRequest(webResource: WebResource): Promise<WebResource>;
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
import { WebResource } from "../webResource";
|
||||
export interface ServiceClientCredentials {
|
||||
/**
|
||||
* Signs a request with the Authentication header.
|
||||
*
|
||||
* @param {WebResource} webResource The WebResource/request to be signed.
|
||||
* @returns {Promise<WebResource>} The signed request object;
|
||||
*/
|
||||
signRequest(webResource: WebResource): Promise<WebResource>;
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
import { WebResource } from "../webResource";
|
||||
import { ServiceClientCredentials } from "./serviceClientCredentials";
|
||||
/**
|
||||
* Creates a new TokenCredentials object.
|
||||
*
|
||||
* @constructor
|
||||
* @param {string} token The token.
|
||||
* @param {string} authorizationScheme The authorization scheme.
|
||||
*/
|
||||
export declare class TokenCredentials implements ServiceClientCredentials {
|
||||
token: string;
|
||||
authorizationScheme: string;
|
||||
constructor(token: string, authorizationScheme?: string);
|
||||
/**
|
||||
* Signs a request with the Authentication header.
|
||||
*
|
||||
* @param {WebResource} The WebResource to be signed.
|
||||
* @return {Promise<WebResource>} The signed request object.
|
||||
*/
|
||||
signRequest(webResource: WebResource): Promise<WebResource>;
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
import { WebResource } from "../webResource";
|
||||
import { HttpOperationResponse } from "../httpOperationResponse";
|
||||
export declare class BaseFilter {
|
||||
constructor();
|
||||
before(request: WebResource): Promise<WebResource>;
|
||||
after(response: HttpOperationResponse): Promise<HttpOperationResponse>;
|
||||
}
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче