UNPKG

12.3 kBJavaScriptView Raw
1"use strict";
2/**
3 * -------------------------------------------------------------------------------------------
4 * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License.
5 * See License in the project root for license information.
6 * -------------------------------------------------------------------------------------------
7 */
8Object.defineProperty(exports, "__esModule", { value: true });
9var tslib_1 = require("tslib");
10var MiddlewareControl_1 = require("./MiddlewareControl");
11var MiddlewareUtil_1 = require("./MiddlewareUtil");
12var ChaosHandlerData_1 = require("./options/ChaosHandlerData");
13var ChaosHandlerOptions_1 = require("./options/ChaosHandlerOptions");
14var ChaosStrategy_1 = require("./options/ChaosStrategy");
15/**
16 * Class representing ChaosHandler
17 * @class
18 * Class
19 * @implements Middleware
20 */
21var ChaosHandler = /** @class */ (function () {
22 /**
23 * @public
24 * @constructor
25 * To create an instance of Testing Handler
26 * @param {ChaosHandlerOptions} [options = new ChaosHandlerOptions()] - The testing handler options instance
27 * @param manualMap - The Map passed by user containing url-statusCode info
28 * @returns An instance of Testing Handler
29 */
30 function ChaosHandler(options, manualMap) {
31 if (options === void 0) { options = new ChaosHandlerOptions_1.ChaosHandlerOptions(); }
32 this.options = options;
33 this.manualMap = manualMap;
34 }
35 /**
36 * Generates responseHeader
37 * @private
38 * @param {number} statusCode - the status code to be returned for the request
39 * @param {string} requestID - request id
40 * @param {string} requestDate - date of the request
41 * @returns response Header
42 */
43 ChaosHandler.prototype.createResponseHeaders = function (statusCode, requestID, requestDate) {
44 var responseHeader = new Headers();
45 responseHeader.append("Cache-Control", "no-store");
46 responseHeader.append("request-id", requestID);
47 responseHeader.append("client-request-id", requestID);
48 responseHeader.append("x-ms-ags-diagnostic", "");
49 responseHeader.append("Date", requestDate);
50 responseHeader.append("Strict-Transport-Security", "");
51 if (statusCode === 429) {
52 // throttling case has to have a timeout scenario
53 responseHeader.append("retry-after", "300");
54 }
55 return responseHeader;
56 };
57 /**
58 * Generates responseBody
59 * @private
60 * @param {number} statusCode - the status code to be returned for the request
61 * @param {string} statusMessage - the status message to be returned for the request
62 * @param {string} requestID - request id
63 * @param {string} requestDate - date of the request
64 * @param {any?} requestBody - the request body to be returned for the request
65 * @returns response body
66 */
67 ChaosHandler.prototype.createResponseBody = function (statusCode, statusMessage, requestID, requestDate, responseBody) {
68 if (responseBody) {
69 return responseBody;
70 }
71 var body;
72 if (statusCode >= 400) {
73 var codeMessage = ChaosHandlerData_1.httpStatusCode[statusCode];
74 var errMessage = statusMessage;
75 body = {
76 error: {
77 code: codeMessage,
78 message: errMessage,
79 innerError: {
80 "request-id": requestID,
81 date: requestDate,
82 },
83 },
84 };
85 }
86 else {
87 body = {};
88 }
89 return body;
90 };
91 /**
92 * creates a response
93 * @private
94 * @param {ChaosHandlerOptions} ChaosHandlerOptions - The ChaosHandlerOptions object
95 * @param {Context} context - Contains the context of the request
96 */
97 ChaosHandler.prototype.createResponse = function (chaosHandlerOptions, context) {
98 try {
99 var responseBody = void 0;
100 var responseHeader = void 0;
101 var requestID = void 0;
102 var requestDate = void 0;
103 var requestURL = context.request;
104 requestID = MiddlewareUtil_1.generateUUID();
105 requestDate = new Date();
106 responseHeader = this.createResponseHeaders(chaosHandlerOptions.statusCode, requestID, requestDate.toString());
107 responseBody = this.createResponseBody(chaosHandlerOptions.statusCode, chaosHandlerOptions.statusMessage, requestID, requestDate.toString(), chaosHandlerOptions.responseBody);
108 var init = { url: requestURL, status: chaosHandlerOptions.statusCode, statusText: chaosHandlerOptions.statusMessage, headers: responseHeader };
109 context.response = new Response(responseBody, init);
110 }
111 catch (error) {
112 throw error;
113 }
114 };
115 /**
116 * Decides whether to send the request to the graph or not
117 * @private
118 * @param {ChaosHandlerOptions} chaosHandlerOptions - A ChaosHandlerOptions object
119 * @param {Context} context - Contains the context of the request
120 * @returns nothing
121 */
122 ChaosHandler.prototype.sendRequest = function (chaosHandlerOptions, context) {
123 return tslib_1.__awaiter(this, void 0, void 0, function () {
124 var error_1;
125 return tslib_1.__generator(this, function (_a) {
126 switch (_a.label) {
127 case 0:
128 _a.trys.push([0, 4, , 5]);
129 this.setStatusCode(chaosHandlerOptions, context.request, context.options.method);
130 if (!!chaosHandlerOptions.statusCode) return [3 /*break*/, 2];
131 return [4 /*yield*/, this.nextMiddleware.execute(context)];
132 case 1:
133 _a.sent();
134 return [3 /*break*/, 3];
135 case 2:
136 this.createResponse(chaosHandlerOptions, context);
137 _a.label = 3;
138 case 3: return [3 /*break*/, 5];
139 case 4:
140 error_1 = _a.sent();
141 throw error_1;
142 case 5: return [2 /*return*/];
143 }
144 });
145 });
146 };
147 /**
148 * Fetches a random status code for the RANDOM mode from the predefined array
149 * @private
150 * @param {string} requestMethod - the API method for the request
151 * @returns a random status code from a given set of status codes
152 */
153 ChaosHandler.prototype.getRandomStatusCode = function (requestMethod) {
154 try {
155 var statusCodeArray = ChaosHandlerData_1.methodStatusCode[requestMethod];
156 return statusCodeArray[Math.floor(Math.random() * statusCodeArray.length)];
157 }
158 catch (error) {
159 throw error;
160 }
161 };
162 /**
163 * To fetch the relative URL out of the complete URL using a predefined regex pattern
164 * @private
165 * @param {string} urlMethod - the complete URL
166 * @returns the string as relative URL
167 */
168 ChaosHandler.prototype.getRelativeURL = function (urlMethod) {
169 var pattern = /https?:\/\/graph\.microsoft\.com\/[^/]+(.+?)(\?|$)/;
170 var relativeURL;
171 if (pattern.exec(urlMethod) !== null) {
172 relativeURL = pattern.exec(urlMethod)[1];
173 }
174 return relativeURL;
175 };
176 /**
177 * To fetch the status code from the map(if needed), then returns response by calling createResponse
178 * @private
179 * @param {ChaosHandlerOptions} ChaosHandlerOptions - The ChaosHandlerOptions object
180 * @param {string} requestURL - the URL for the request
181 * @param {string} requestMethod - the API method for the request
182 */
183 ChaosHandler.prototype.setStatusCode = function (chaosHandlerOptions, requestURL, requestMethod) {
184 var _this = this;
185 try {
186 if (chaosHandlerOptions.chaosStrategy === ChaosStrategy_1.ChaosStrategy.MANUAL) {
187 if (chaosHandlerOptions.statusCode === undefined) {
188 // manual mode with no status code, can be a global level or request level without statusCode
189 var relativeURL_1 = this.getRelativeURL(requestURL);
190 if (this.manualMap.get(relativeURL_1) !== undefined) {
191 // checking Manual Map for exact match
192 if (this.manualMap.get(relativeURL_1).get(requestMethod) !== undefined) {
193 chaosHandlerOptions.statusCode = this.manualMap.get(relativeURL_1).get(requestMethod);
194 }
195 // else statusCode would be undefined
196 }
197 else {
198 // checking for regex match if exact match doesn't work
199 this.manualMap.forEach(function (value, key) {
200 var regexURL = new RegExp(key + "$");
201 if (regexURL.test(relativeURL_1)) {
202 if (_this.manualMap.get(key).get(requestMethod) !== undefined) {
203 chaosHandlerOptions.statusCode = _this.manualMap.get(key).get(requestMethod);
204 }
205 // else statusCode would be undefined
206 }
207 });
208 }
209 // Case of redirection or request url not in map ---> statusCode would be undefined
210 }
211 }
212 else {
213 // Handling the case of Random here
214 if (Math.floor(Math.random() * 100) < chaosHandlerOptions.chaosPercentage) {
215 chaosHandlerOptions.statusCode = this.getRandomStatusCode(requestMethod);
216 }
217 // else statusCode would be undefined
218 }
219 }
220 catch (error) {
221 throw error;
222 }
223 };
224 /**
225 * To get the options for execution of the middleware
226 * @private
227 * @param {Context} context - The context object
228 * @returns options for middleware execution
229 */
230 ChaosHandler.prototype.getOptions = function (context) {
231 var options;
232 if (context.middlewareControl instanceof MiddlewareControl_1.MiddlewareControl) {
233 options = context.middlewareControl.getMiddlewareOptions(ChaosHandlerOptions_1.ChaosHandlerOptions);
234 }
235 if (typeof options === "undefined") {
236 options = Object.assign(new ChaosHandlerOptions_1.ChaosHandlerOptions(), this.options);
237 }
238 return options;
239 };
240 /**
241 * To execute the current middleware
242 * @public
243 * @async
244 * @param {Context} context - The context object of the request
245 * @returns A Promise that resolves to nothing
246 */
247 ChaosHandler.prototype.execute = function (context) {
248 return tslib_1.__awaiter(this, void 0, void 0, function () {
249 var chaosHandlerOptions, error_2;
250 return tslib_1.__generator(this, function (_a) {
251 switch (_a.label) {
252 case 0:
253 _a.trys.push([0, 2, , 3]);
254 chaosHandlerOptions = this.getOptions(context);
255 return [4 /*yield*/, this.sendRequest(chaosHandlerOptions, context)];
256 case 1: return [2 /*return*/, _a.sent()];
257 case 2:
258 error_2 = _a.sent();
259 throw error_2;
260 case 3: return [2 /*return*/];
261 }
262 });
263 });
264 };
265 /**
266 * @public
267 * To set the next middleware in the chain
268 * @param {Middleware} next - The middleware instance
269 * @returns Nothing
270 */
271 ChaosHandler.prototype.setNext = function (next) {
272 this.nextMiddleware = next;
273 };
274 return ChaosHandler;
275}());
276exports.ChaosHandler = ChaosHandler;
277//# sourceMappingURL=ChaosHandler.js.map
\No newline at end of file