@microsoft/microsoft-graph-client
Version:
Microsoft Graph Client Library
245 lines • 11.2 kB
JavaScript
/**
* -------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License.
* See License in the project root for license information.
* -------------------------------------------------------------------------------------------
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.ChaosHandler = void 0;
var tslib_1 = require("tslib");
var MiddlewareControl_1 = require("./MiddlewareControl");
var MiddlewareUtil_1 = require("./MiddlewareUtil");
var ChaosHandlerData_1 = require("./options/ChaosHandlerData");
var ChaosHandlerOptions_1 = require("./options/ChaosHandlerOptions");
var ChaosStrategy_1 = require("./options/ChaosStrategy");
/**
* Class representing ChaosHandler
* @class
* Class
* @implements Middleware
*/
var ChaosHandler = /** @class */ (function () {
/**
* @public
* @constructor
* To create an instance of Testing Handler
* @param {ChaosHandlerOptions} [options = new ChaosHandlerOptions()] - The testing handler options instance
* @param manualMap - The Map passed by user containing url-statusCode info
* @returns An instance of Testing Handler
*/
function ChaosHandler(options, manualMap) {
if (options === void 0) { options = new ChaosHandlerOptions_1.ChaosHandlerOptions(); }
this.options = options;
this.manualMap = manualMap;
}
/**
* Generates responseHeader
* @private
* @param {ChaosHandlerOptions} chaosHandlerOptions - The ChaosHandlerOptions object
* @param {string} requestID - request id
* @param {string} requestDate - date of the request
* @returns response Header
*/
ChaosHandler.prototype.createResponseHeaders = function (chaosHandlerOptions, requestID, requestDate) {
var responseHeader = chaosHandlerOptions.headers ? new Headers(chaosHandlerOptions.headers) : new Headers();
responseHeader.append("Cache-Control", "no-store");
responseHeader.append("request-id", requestID);
responseHeader.append("client-request-id", requestID);
responseHeader.append("x-ms-ags-diagnostic", "");
responseHeader.append("Date", requestDate);
responseHeader.append("Strict-Transport-Security", "");
if (chaosHandlerOptions.statusCode === 429) {
// throttling case has to have a timeout scenario
responseHeader.append("retry-after", "3");
}
return responseHeader;
};
/**
* Generates responseBody
* @private
* @param {ChaosHandlerOptions} chaosHandlerOptions - The ChaosHandlerOptions object
* @param {string} requestID - request id
* @param {string} requestDate - date of the request
* * @returns response body
*/
ChaosHandler.prototype.createResponseBody = function (chaosHandlerOptions, requestID, requestDate) {
if (chaosHandlerOptions.responseBody) {
return chaosHandlerOptions.responseBody;
}
var body;
if (chaosHandlerOptions.statusCode >= 400) {
var codeMessage = ChaosHandlerData_1.httpStatusCode[chaosHandlerOptions.statusCode];
var errMessage = chaosHandlerOptions.statusMessage;
body = {
error: {
code: codeMessage,
message: errMessage,
innerError: {
"request-id": requestID,
date: requestDate,
},
},
};
}
else {
body = {};
}
return body;
};
/**
* creates a response
* @private
* @param {ChaosHandlerOptions} chaosHandlerOptions - The ChaosHandlerOptions object
* @param {Context} context - Contains the context of the request
*/
ChaosHandler.prototype.createResponse = function (chaosHandlerOptions, context) {
var requestURL = context.request;
var requestID = (0, MiddlewareUtil_1.generateUUID)();
var requestDate = new Date();
var responseHeader = this.createResponseHeaders(chaosHandlerOptions, requestID, requestDate.toString());
var responseBody = this.createResponseBody(chaosHandlerOptions, requestID, requestDate.toString());
var init = { url: requestURL, status: chaosHandlerOptions.statusCode, statusText: chaosHandlerOptions.statusMessage, headers: responseHeader };
context.response = new Response(typeof responseBody === "string" ? responseBody : JSON.stringify(responseBody), init);
};
/**
* Decides whether to send the request to the graph or not
* @private
* @param {ChaosHandlerOptions} chaosHandlerOptions - A ChaosHandlerOptions object
* @param {Context} context - Contains the context of the request
* @returns nothing
*/
ChaosHandler.prototype.sendRequest = function (chaosHandlerOptions, context) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
this.setStatusCode(chaosHandlerOptions, context.request, context.options.method);
if (!((chaosHandlerOptions.chaosStrategy === ChaosStrategy_1.ChaosStrategy.MANUAL && !this.nextMiddleware) || Math.floor(Math.random() * 100) < chaosHandlerOptions.chaosPercentage)) return [3 /*break*/, 1];
this.createResponse(chaosHandlerOptions, context);
return [3 /*break*/, 3];
case 1:
if (!this.nextMiddleware) return [3 /*break*/, 3];
return [4 /*yield*/, this.nextMiddleware.execute(context)];
case 2:
_a.sent();
_a.label = 3;
case 3: return [2 /*return*/];
}
});
});
};
/**
* Fetches a random status code for the RANDOM mode from the predefined array
* @private
* @param {string} requestMethod - the API method for the request
* @returns a random status code from a given set of status codes
*/
ChaosHandler.prototype.getRandomStatusCode = function (requestMethod) {
var statusCodeArray = ChaosHandlerData_1.methodStatusCode[requestMethod];
return statusCodeArray[Math.floor(Math.random() * statusCodeArray.length)];
};
/**
* To fetch the relative URL out of the complete URL using a predefined regex pattern
* @private
* @param {string} urlMethod - the complete URL
* @returns the string as relative URL
*/
ChaosHandler.prototype.getRelativeURL = function (urlMethod) {
var pattern = /https?:\/\/graph\.microsoft\.com\/[^/]+(.+?)(\?|$)/;
var relativeURL;
if (pattern.exec(urlMethod) !== null) {
relativeURL = pattern.exec(urlMethod)[1];
}
return relativeURL;
};
/**
* To fetch the status code from the map(if needed), then returns response by calling createResponse
* @private
* @param {ChaosHandlerOptions} chaosHandlerOptions - The ChaosHandlerOptions object
* @param {string} requestURL - the URL for the request
* @param {string} requestMethod - the API method for the request
*/
ChaosHandler.prototype.setStatusCode = function (chaosHandlerOptions, requestURL, requestMethod) {
var _this = this;
if (chaosHandlerOptions.chaosStrategy === ChaosStrategy_1.ChaosStrategy.MANUAL) {
if (chaosHandlerOptions.statusCode === undefined) {
// manual mode with no status code, can be a global level or request level without statusCode
var relativeURL_1 = this.getRelativeURL(requestURL);
if (this.manualMap.get(relativeURL_1) !== undefined) {
// checking Manual Map for exact match
if (this.manualMap.get(relativeURL_1).get(requestMethod) !== undefined) {
chaosHandlerOptions.statusCode = this.manualMap.get(relativeURL_1).get(requestMethod);
}
// else statusCode would be undefined
}
else {
// checking for regex match if exact match doesn't work
this.manualMap.forEach(function (value, key) {
var regexURL = new RegExp(key + "$");
if (regexURL.test(relativeURL_1)) {
if (_this.manualMap.get(key).get(requestMethod) !== undefined) {
chaosHandlerOptions.statusCode = _this.manualMap.get(key).get(requestMethod);
}
// else statusCode would be undefined
}
});
}
// Case of redirection or request url not in map ---> statusCode would be undefined
}
}
else {
// Handling the case of Random here
chaosHandlerOptions.statusCode = this.getRandomStatusCode(requestMethod);
// else statusCode would be undefined
}
};
/**
* To get the options for execution of the middleware
* @private
* @param {Context} context - The context object
* @returns options for middleware execution
*/
ChaosHandler.prototype.getOptions = function (context) {
var options;
if (context.middlewareControl instanceof MiddlewareControl_1.MiddlewareControl) {
options = context.middlewareControl.getMiddlewareOptions(ChaosHandlerOptions_1.ChaosHandlerOptions);
}
if (typeof options === "undefined") {
options = Object.assign(new ChaosHandlerOptions_1.ChaosHandlerOptions(), this.options);
}
return options;
};
/**
* To execute the current middleware
* @public
* @async
* @param {Context} context - The context object of the request
* @returns A Promise that resolves to nothing
*/
ChaosHandler.prototype.execute = function (context) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var chaosHandlerOptions;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
chaosHandlerOptions = this.getOptions(context);
return [4 /*yield*/, this.sendRequest(chaosHandlerOptions, context)];
case 1: return [2 /*return*/, _a.sent()];
}
});
});
};
/**
* @public
* To set the next middleware in the chain
* @param {Middleware} next - The middleware instance
* @returns Nothing
*/
ChaosHandler.prototype.setNext = function (next) {
this.nextMiddleware = next;
};
return ChaosHandler;
}());
exports.ChaosHandler = ChaosHandler;
//# sourceMappingURL=ChaosHandler.js.map
;