UNPKG

11.2 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 RequestMethod_1 = require("../RequestMethod");
11var MiddlewareControl_1 = require("./MiddlewareControl");
12var MiddlewareUtil_1 = require("./MiddlewareUtil");
13var RedirectHandlerOptions_1 = require("./options/RedirectHandlerOptions");
14var TelemetryHandlerOptions_1 = require("./options/TelemetryHandlerOptions");
15/**
16 * @class
17 * Class
18 * @implements Middleware
19 * Class representing RedirectHandler
20 */
21var RedirectHandler = /** @class */ (function () {
22 /**
23 * @public
24 * @constructor
25 * To create an instance of RedirectHandler
26 * @param {RedirectHandlerOptions} [options = new RedirectHandlerOptions()] - The redirect handler options instance
27 * @returns An instance of RedirectHandler
28 */
29 function RedirectHandler(options) {
30 if (options === void 0) { options = new RedirectHandlerOptions_1.RedirectHandlerOptions(); }
31 this.options = options;
32 }
33 /**
34 * @private
35 * To check whether the response has the redirect status code or not
36 * @param {Response} response - The response object
37 * @returns A boolean representing whether the response contains the redirect status code or not
38 */
39 RedirectHandler.prototype.isRedirect = function (response) {
40 return RedirectHandler.REDIRECT_STATUS_CODES.indexOf(response.status) !== -1;
41 };
42 /**
43 * @private
44 * To check whether the response has location header or not
45 * @param {Response} response - The response object
46 * @returns A boolean representing the whether the response has location header or not
47 */
48 RedirectHandler.prototype.hasLocationHeader = function (response) {
49 return response.headers.has(RedirectHandler.LOCATION_HEADER);
50 };
51 /**
52 * @private
53 * To get the redirect url from location header in response object
54 * @param {Response} response - The response object
55 * @returns A redirect url from location header
56 */
57 RedirectHandler.prototype.getLocationHeader = function (response) {
58 return response.headers.get(RedirectHandler.LOCATION_HEADER);
59 };
60 /**
61 * @private
62 * To check whether the given url is a relative url or not
63 * @param {string} url - The url string value
64 * @returns A boolean representing whether the given url is a relative url or not
65 */
66 RedirectHandler.prototype.isRelativeURL = function (url) {
67 return url.indexOf("://") === -1;
68 };
69 /**
70 * @private
71 * To check whether the authorization header in the request should be dropped for consequent redirected requests
72 * @param {string} requestUrl - The request url value
73 * @param {string} redirectUrl - The redirect url value
74 * @returns A boolean representing whether the authorization header in the request should be dropped for consequent redirected requests
75 */
76 RedirectHandler.prototype.shouldDropAuthorizationHeader = function (requestUrl, redirectUrl) {
77 var schemeHostRegex = /^[A-Za-z].+?:\/\/.+?(?=\/|$)/;
78 var requestMatches = schemeHostRegex.exec(requestUrl);
79 var requestAuthority;
80 var redirectAuthority;
81 if (requestMatches !== null) {
82 requestAuthority = requestMatches[0];
83 }
84 var redirectMatches = schemeHostRegex.exec(redirectUrl);
85 if (redirectMatches !== null) {
86 redirectAuthority = redirectMatches[0];
87 }
88 return typeof requestAuthority !== "undefined" && typeof redirectAuthority !== "undefined" && requestAuthority !== redirectAuthority;
89 };
90 /**
91 * @private
92 * @async
93 * To update a request url with the redirect url
94 * @param {string} redirectUrl - The redirect url value
95 * @param {Context} context - The context object value
96 * @returns Nothing
97 */
98 RedirectHandler.prototype.updateRequestUrl = function (redirectUrl, context) {
99 return tslib_1.__awaiter(this, void 0, void 0, function () {
100 var _a, _b;
101 return tslib_1.__generator(this, function (_c) {
102 switch (_c.label) {
103 case 0:
104 _a = context;
105 if (!(typeof context.request === "string")) return [3 /*break*/, 1];
106 _b = redirectUrl;
107 return [3 /*break*/, 3];
108 case 1: return [4 /*yield*/, MiddlewareUtil_1.cloneRequestWithNewUrl(redirectUrl, context.request)];
109 case 2:
110 _b = _c.sent();
111 _c.label = 3;
112 case 3:
113 _a.request = _b;
114 return [2 /*return*/];
115 }
116 });
117 });
118 };
119 /**
120 * @private
121 * To get the options for execution of the middleware
122 * @param {Context} context - The context object
123 * @returns A options for middleware execution
124 */
125 RedirectHandler.prototype.getOptions = function (context) {
126 var options;
127 if (context.middlewareControl instanceof MiddlewareControl_1.MiddlewareControl) {
128 options = context.middlewareControl.getMiddlewareOptions(RedirectHandlerOptions_1.RedirectHandlerOptions);
129 }
130 if (typeof options === "undefined") {
131 options = Object.assign(new RedirectHandlerOptions_1.RedirectHandlerOptions(), this.options);
132 }
133 return options;
134 };
135 /**
136 * @private
137 * @async
138 * To execute the next middleware and to handle in case of redirect response returned by the server
139 * @param {Context} context - The context object
140 * @param {number} redirectCount - The redirect count value
141 * @param {RedirectHandlerOptions} options - The redirect handler options instance
142 * @returns A promise that resolves to nothing
143 */
144 RedirectHandler.prototype.executeWithRedirect = function (context, redirectCount, options) {
145 return tslib_1.__awaiter(this, void 0, void 0, function () {
146 var response, redirectUrl, error_1;
147 return tslib_1.__generator(this, function (_a) {
148 switch (_a.label) {
149 case 0:
150 _a.trys.push([0, 8, , 9]);
151 return [4 /*yield*/, this.nextMiddleware.execute(context)];
152 case 1:
153 _a.sent();
154 response = context.response;
155 if (!(redirectCount < options.maxRedirects && this.isRedirect(response) && this.hasLocationHeader(response) && options.shouldRedirect(response))) return [3 /*break*/, 6];
156 ++redirectCount;
157 if (!(response.status === RedirectHandler.STATUS_CODE_SEE_OTHER)) return [3 /*break*/, 2];
158 context.options.method = RequestMethod_1.RequestMethod.GET;
159 delete context.options.body;
160 return [3 /*break*/, 4];
161 case 2:
162 redirectUrl = this.getLocationHeader(response);
163 if (!this.isRelativeURL(redirectUrl) && this.shouldDropAuthorizationHeader(response.url, redirectUrl)) {
164 delete context.options.headers[RedirectHandler.AUTHORIZATION_HEADER];
165 }
166 return [4 /*yield*/, this.updateRequestUrl(redirectUrl, context)];
167 case 3:
168 _a.sent();
169 _a.label = 4;
170 case 4: return [4 /*yield*/, this.executeWithRedirect(context, redirectCount, options)];
171 case 5:
172 _a.sent();
173 return [3 /*break*/, 7];
174 case 6: return [2 /*return*/];
175 case 7: return [3 /*break*/, 9];
176 case 8:
177 error_1 = _a.sent();
178 throw error_1;
179 case 9: return [2 /*return*/];
180 }
181 });
182 });
183 };
184 /**
185 * @public
186 * @async
187 * To execute the current middleware
188 * @param {Context} context - The context object of the request
189 * @returns A Promise that resolves to nothing
190 */
191 RedirectHandler.prototype.execute = function (context) {
192 return tslib_1.__awaiter(this, void 0, void 0, function () {
193 var redirectCount, options, error_2;
194 return tslib_1.__generator(this, function (_a) {
195 switch (_a.label) {
196 case 0:
197 _a.trys.push([0, 2, , 3]);
198 redirectCount = 0;
199 options = this.getOptions(context);
200 context.options.redirect = RedirectHandler.MANUAL_REDIRECT;
201 TelemetryHandlerOptions_1.TelemetryHandlerOptions.updateFeatureUsageFlag(context, TelemetryHandlerOptions_1.FeatureUsageFlag.REDIRECT_HANDLER_ENABLED);
202 return [4 /*yield*/, this.executeWithRedirect(context, redirectCount, options)];
203 case 1: return [2 /*return*/, _a.sent()];
204 case 2:
205 error_2 = _a.sent();
206 throw error_2;
207 case 3: return [2 /*return*/];
208 }
209 });
210 });
211 };
212 /**
213 * @public
214 * To set the next middleware in the chain
215 * @param {Middleware} next - The middleware instance
216 * @returns Nothing
217 */
218 RedirectHandler.prototype.setNext = function (next) {
219 this.nextMiddleware = next;
220 };
221 /**
222 * @private
223 * @static
224 * A member holding the array of redirect status codes
225 */
226 RedirectHandler.REDIRECT_STATUS_CODES = [
227 301,
228 302,
229 303,
230 307,
231 308,
232 ];
233 /**
234 * @private
235 * @static
236 * A member holding SeeOther status code
237 */
238 RedirectHandler.STATUS_CODE_SEE_OTHER = 303;
239 /**
240 * @private
241 * @static
242 * A member holding the name of the location header
243 */
244 RedirectHandler.LOCATION_HEADER = "Location";
245 /**
246 * @private
247 * @static
248 * A member representing the authorization header name
249 */
250 RedirectHandler.AUTHORIZATION_HEADER = "Authorization";
251 /**
252 * @private
253 * @static
254 * A member holding the manual redirect value
255 */
256 RedirectHandler.MANUAL_REDIRECT = "manual";
257 return RedirectHandler;
258}());
259exports.RedirectHandler = RedirectHandler;
260//# sourceMappingURL=RedirectHandler.js.map
\No newline at end of file