1 | ;
|
2 |
|
3 | Object.defineProperty(exports, "__esModule", {
|
4 | value: true
|
5 | });
|
6 |
|
7 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
|
8 |
|
9 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
10 |
|
11 | var https = require("https");
|
12 | var http = require("http");
|
13 | var request = require("request");
|
14 | var querystring = require("querystring");
|
15 |
|
16 | var HttpClient = function () {
|
17 | function HttpClient(options, credentials) {
|
18 | _classCallCheck(this, HttpClient);
|
19 |
|
20 | this.credentials = credentials;
|
21 | this.host = options.host || "rest.nexmo.com";
|
22 | this.port = options.port || 443;
|
23 | this.https = options.https || https;
|
24 | this.http = options.http || http;
|
25 | this.headers = {
|
26 | "Content-Type": "application/x-www-form-urlencoded",
|
27 | Accept: "application/json"
|
28 | };
|
29 | this.logger = options.logger;
|
30 | this.timeout = options.timeout;
|
31 | this.requestLib = request;
|
32 |
|
33 | if (options.userAgent) {
|
34 | this.headers["User-Agent"] = options.userAgent;
|
35 | }
|
36 | }
|
37 |
|
38 | _createClass(HttpClient, [{
|
39 | key: "request",
|
40 | value: function request(endpoint, method, callback) {
|
41 | var _this = this;
|
42 |
|
43 | var skipJsonParsing = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
|
44 |
|
45 | if (typeof method === "function") {
|
46 | callback = method;
|
47 | endpoint.method = endpoint.method || "GET";
|
48 | } else if (typeof method !== "undefined") {
|
49 | endpoint.method = method;
|
50 | }
|
51 |
|
52 | if (endpoint.method === "POST" || endpoint.method === "DELETE") {
|
53 | // TODO: verify the following fix is required
|
54 | // Fix broken due ot 411 Content-Length error now sent by Nexmo API
|
55 | // PL 2016-Sept-6 - commented out Content-Length 0
|
56 | // headers['Content-Length'] = 0;
|
57 | }
|
58 | var options = {
|
59 | host: endpoint.host ? endpoint.host : this.host,
|
60 | port: this.port,
|
61 | path: endpoint.path,
|
62 | method: endpoint.method,
|
63 | headers: Object.assign({}, this.headers)
|
64 | };
|
65 |
|
66 | if (this.timeout !== undefined) {
|
67 | options.timeout = this.timeout;
|
68 | }
|
69 |
|
70 | // Allow existing headers to be overridden
|
71 | // Allow new headers to be added
|
72 | if (endpoint.headers) {
|
73 | Object.keys(endpoint.headers).forEach(function (key) {
|
74 | options.headers[key] = endpoint.headers[key];
|
75 | });
|
76 | }
|
77 |
|
78 | this.logger.info("Request:", options, "\nBody:", endpoint.body);
|
79 | var request;
|
80 |
|
81 | if (options.port === 443) {
|
82 | request = this.https.request(options);
|
83 | } else {
|
84 | request = this.http.request(options);
|
85 | }
|
86 |
|
87 | request.end(endpoint.body);
|
88 |
|
89 | // Keep an array of String or Buffers,
|
90 | // depending on content type (binary or JSON) of response
|
91 | var responseData = [];
|
92 |
|
93 | request.on("response", function (response) {
|
94 | var isBinary = response.headers["content-type"] === "application/octet-stream";
|
95 | if (!isBinary) {
|
96 | response.setEncoding("utf8");
|
97 | }
|
98 |
|
99 | response.on("data", function (chunk) {
|
100 | responseData.push(chunk);
|
101 | });
|
102 |
|
103 | response.on("end", function () {
|
104 | _this.logger.info("response ended:", response.statusCode);
|
105 | if (callback) {
|
106 | if (isBinary) {
|
107 | responseData = Buffer.concat(responseData);
|
108 | }
|
109 |
|
110 | _this.__parseResponse(response, responseData, endpoint.method, callback, skipJsonParsing);
|
111 | }
|
112 | });
|
113 | response.on("close", function (e) {
|
114 | if (e) {
|
115 | _this.logger.error("problem with API request detailed stacktrace below ");
|
116 | _this.logger.error(e);
|
117 | callback(e);
|
118 | }
|
119 | });
|
120 | });
|
121 | request.on("error", function (e) {
|
122 | _this.logger.error("problem with API request detailed stacktrace below ");
|
123 | _this.logger.error(e);
|
124 | callback(e);
|
125 | });
|
126 | }
|
127 | }, {
|
128 | key: "__parseResponse",
|
129 | value: function __parseResponse(httpResponse, data, method, callback, skipJsonParsing) {
|
130 | var isArrayOrBuffer = data instanceof Array || data instanceof Buffer;
|
131 | if (!isArrayOrBuffer) {
|
132 | throw new Error("data should be of type Array or Buffer");
|
133 | }
|
134 |
|
135 | var status = httpResponse.statusCode;
|
136 | var headers = httpResponse.headers;
|
137 |
|
138 | var response = null;
|
139 | var error = null;
|
140 |
|
141 | try {
|
142 | if (status >= 500) {
|
143 | error = { message: "Server Error", statusCode: status };
|
144 | } else if (httpResponse.headers["content-type"] === "application/octet-stream") {
|
145 | response = data;
|
146 | } else if (status === 429) {
|
147 | // 429 does not return a parsable body
|
148 | if (!headers["retry-after"]) {
|
149 | // retry based on allowed per second
|
150 | var retryAfterMillis = method === "POST" ? 1000 / 2 : 1000 / 5;
|
151 | headers["retry-after"] = retryAfterMillis;
|
152 | }
|
153 | error = { body: data.join("") };
|
154 | } else if (status === 204) {
|
155 | response = null;
|
156 | } else if (status >= 400 || status < 200) {
|
157 | error = { body: JSON.parse(data.join("")), headers: headers };
|
158 | } else if (method !== "DELETE") {
|
159 | if (!!skipJsonParsing) {
|
160 | response = data.join("");
|
161 | } else {
|
162 | response = JSON.parse(data.join(""));
|
163 | }
|
164 | } else {
|
165 | response = data;
|
166 | }
|
167 | } catch (parseError) {
|
168 | this.logger.error(parseError);
|
169 | this.logger.error("could not convert API response to JSON, above error is ignored and raw API response is returned to client");
|
170 | this.logger.error("Raw Error message from API ");
|
171 | this.logger.error("\"" + data + "\"");
|
172 |
|
173 | error = {
|
174 | status: status,
|
175 | message: "The API response could not be parsed.",
|
176 | body: data.join(""),
|
177 | parseError: parseError
|
178 | };
|
179 | }
|
180 |
|
181 | if (error) {
|
182 | error.statusCode = status;
|
183 | error.headers = headers;
|
184 | }
|
185 |
|
186 | if (typeof callback === "function") {
|
187 | callback(error, response);
|
188 | }
|
189 | }
|
190 | }, {
|
191 | key: "_addLimitedAccessMessageToErrors",
|
192 | value: function _addLimitedAccessMessageToErrors(callback, limitedAccessStatus) {
|
193 | return function (err, data) {
|
194 | if (err && err.status == limitedAccessStatus) {
|
195 | err._INFO_ = "This endpoint may need activating on your account. Please email support@nexmo.com for more information";
|
196 | }
|
197 |
|
198 | return callback(err, data);
|
199 | };
|
200 | }
|
201 | }, {
|
202 | key: "get",
|
203 | value: function get(path, params, callback) {
|
204 | var useJwt = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
|
205 |
|
206 | if (!callback) {
|
207 | if (typeof params == "function") {
|
208 | callback = params;
|
209 | params = {};
|
210 | }
|
211 | }
|
212 |
|
213 | params = params || {};
|
214 | if (!useJwt) {
|
215 | params["api_key"] = this.credentials.apiKey;
|
216 | params["api_secret"] = this.credentials.apiSecret;
|
217 | }
|
218 |
|
219 | path = path + "?" + querystring.stringify(params);
|
220 |
|
221 | var headers = { "Content-Type": "application/json" };
|
222 | if (useJwt) {
|
223 | headers["Authorization"] = "Bearer " + this.credentials.generateJwt();
|
224 | }
|
225 |
|
226 | this.request({ path: path, headers: headers }, "GET", callback);
|
227 | }
|
228 | }, {
|
229 | key: "delete",
|
230 | value: function _delete(path, callback, useJwt) {
|
231 | var params = {};
|
232 | if (!useJwt) {
|
233 | params["api_key"] = this.credentials.apiKey;
|
234 | params["api_secret"] = this.credentials.apiSecret;
|
235 | }
|
236 |
|
237 | path = path + "?" + querystring.stringify(params);
|
238 |
|
239 | this.request({ path: path }, "DELETE", callback);
|
240 | }
|
241 | }, {
|
242 | key: "postFile",
|
243 | value: function postFile(path, options, callback, useJwt) {
|
244 | var qs = {};
|
245 | if (!useJwt) {
|
246 | qs["api_key"] = this.credentials.apiKey;
|
247 | qs["api_secret"] = this.credentials.apiSecret;
|
248 | }
|
249 |
|
250 | if (Object.keys(qs).length) {
|
251 | var joinChar = "?";
|
252 | if (path.indexOf(joinChar) !== -1) {
|
253 | joinChar = "&";
|
254 | }
|
255 | path = path + joinChar + querystring.stringify(qs);
|
256 | }
|
257 |
|
258 | var file = options.file;
|
259 | delete options.file; // We don't send this as metadata
|
260 |
|
261 | var formData = {};
|
262 |
|
263 | if (file) {
|
264 | formData["filedata"] = {
|
265 | value: file,
|
266 | options: {
|
267 | filename: options.filename || null
|
268 | }
|
269 | };
|
270 | }
|
271 |
|
272 | if (options.info) {
|
273 | formData.info = JSON.stringify(options.info);
|
274 | }
|
275 |
|
276 | if (options.url) {
|
277 | formData.url = options.url;
|
278 | }
|
279 |
|
280 | this.requestLib.post({
|
281 | url: "https://" + this.host + path,
|
282 | formData: formData,
|
283 | headers: {
|
284 | Authorization: "Bearer " + this.credentials.generateJwt()
|
285 | }
|
286 | }, callback);
|
287 | }
|
288 | }, {
|
289 | key: "post",
|
290 | value: function post(path, params, callback, useJwt) {
|
291 | var qs = {};
|
292 | if (!useJwt) {
|
293 | qs["api_key"] = this.credentials.apiKey;
|
294 | qs["api_secret"] = this.credentials.apiSecret;
|
295 | }
|
296 |
|
297 | var joinChar = "?";
|
298 | if (path.indexOf(joinChar) !== -1) {
|
299 | joinChar = "&";
|
300 | }
|
301 |
|
302 | path = path + joinChar + querystring.stringify(qs);
|
303 |
|
304 | this.request({ path: path, body: querystring.stringify(params) }, "POST", callback);
|
305 | }
|
306 | }, {
|
307 | key: "postJson",
|
308 | value: function postJson(path, params, callback, useJwt) {
|
309 | var qs = {};
|
310 | if (!useJwt) {
|
311 | qs["api_key"] = this.credentials.apiKey;
|
312 | qs["api_secret"] = this.credentials.apiSecret;
|
313 | }
|
314 |
|
315 | var joinChar = "?";
|
316 | if (path.indexOf(joinChar) !== -1) {
|
317 | joinChar = "&";
|
318 | }
|
319 |
|
320 | path = path + joinChar + querystring.stringify(qs);
|
321 |
|
322 | this.request({
|
323 | path: path,
|
324 | body: JSON.stringify(params),
|
325 | headers: { "Content-Type": "application/json" }
|
326 | }, "POST", callback);
|
327 | }
|
328 | }, {
|
329 | key: "postUseQueryString",
|
330 | value: function postUseQueryString(path, params, callback, useJwt) {
|
331 | params = params || {};
|
332 | if (!useJwt) {
|
333 | params["api_key"] = this.credentials.apiKey;
|
334 | params["api_secret"] = this.credentials.apiSecret;
|
335 | }
|
336 |
|
337 | path = path + "?" + querystring.stringify(params);
|
338 |
|
339 | this.request({ path: path }, "POST", callback);
|
340 | }
|
341 | }]);
|
342 |
|
343 | return HttpClient;
|
344 | }();
|
345 |
|
346 | exports.default = HttpClient;
|
347 | module.exports = exports["default"];
|
348 | //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9IdHRwQ2xpZW50LmpzIl0sIm5hbWVzIjpbImh0dHBzIiwicmVxdWlyZSIsImh0dHAiLCJyZXF1ZXN0IiwicXVlcnlzdHJpbmciLCJIdHRwQ2xpZW50Iiwib3B0aW9ucyIsImNyZWRlbnRpYWxzIiwiaG9zdCIsInBvcnQiLCJoZWFkZXJzIiwiQWNjZXB0IiwibG9nZ2VyIiwidGltZW91dCIsInJlcXVlc3RMaWIiLCJ1c2VyQWdlbnQiLCJlbmRwb2ludCIsIm1ldGhvZCIsImNhbGxiYWNrIiwic2tpcEpzb25QYXJzaW5nIiwicGF0aCIsIk9iamVjdCIsImFzc2lnbiIsInVuZGVmaW5lZCIsImtleXMiLCJmb3JFYWNoIiwia2V5IiwiaW5mbyIsImJvZHkiLCJlbmQiLCJyZXNwb25zZURhdGEiLCJvbiIsImlzQmluYXJ5IiwicmVzcG9uc2UiLCJzZXRFbmNvZGluZyIsInB1c2giLCJjaHVuayIsInN0YXR1c0NvZGUiLCJCdWZmZXIiLCJjb25jYXQiLCJfX3BhcnNlUmVzcG9uc2UiLCJlIiwiZXJyb3IiLCJodHRwUmVzcG9uc2UiLCJkYXRhIiwiaXNBcnJheU9yQnVmZmVyIiwiQXJyYXkiLCJFcnJvciIsInN0YXR1cyIsIm1lc3NhZ2UiLCJyZXRyeUFmdGVyTWlsbGlzIiwiam9pbiIsIkpTT04iLCJwYXJzZSIsInBhcnNlRXJyb3IiLCJsaW1pdGVkQWNjZXNzU3RhdHVzIiwiZXJyIiwiX0lORk9fIiwicGFyYW1zIiwidXNlSnd0IiwiYXBpS2V5IiwiYXBpU2VjcmV0Iiwic3RyaW5naWZ5IiwiZ2VuZXJhdGVKd3QiLCJxcyIsImxlbmd0aCIsImpvaW5DaGFyIiwiaW5kZXhPZiIsImZpbGUiLCJmb3JtRGF0YSIsInZhbHVlIiwiZmlsZW5hbWUiLCJ1cmwiLCJwb3N0IiwiQXV0aG9yaXphdGlvbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7OztBQUFBLElBQUlBLFFBQVFDLFFBQVEsT0FBUixDQUFaO0FBQ0EsSUFBSUMsT0FBT0QsUUFBUSxNQUFSLENBQVg7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LEdBQWtCOUQsWUFBWTBELFNBQVosQ0FBc0JFLEVBQXRCLENBQXpCOztBQUVBLFdBQUs3RCxPQUFMLENBQ0U7QUFDRWlCLGNBQU1BLElBRFI7QUFFRVEsY0FBTXdCLEtBQUtVLFNBQUwsQ0FBZUosTUFBZixDQUZSO0FBR0VoRCxpQkFBUyxFQUFFLGdCQUFnQixrQkFBbEI7QUFIWCxPQURGLEVBTUUsTUFORixFQU9FUSxRQVBGO0FBU0Q7Ozt1Q0FFa0JFLEksRUFBTXNDLE0sRUFBUXhDLFEsRUFBVXlDLE0sRUFBUTtBQUNqREQsZUFBU0EsVUFBVSxFQUFuQjtBQUNBLFVBQUksQ0FBQ0MsTUFBTCxFQUFhO0FBQ1hELGVBQU8sU0FBUCxJQUFvQixLQUFLbkQsV0FBTCxDQUFpQnFELE1BQXJDO0FBQ0FGLGVBQU8sWUFBUCxJQUF1QixLQUFLbkQsV0FBTCxDQUFpQnNELFNBQXhDO0FBQ0Q7O0FBRUR6QyxhQUFPQSxPQUFPLEdBQVAsR0FBYWhCLFlBQVkwRCxTQUFaLENBQXNCSixNQUF0QixDQUFwQjs7QUFFQSxXQUFLdkQsT0FBTCxDQUFhLEVBQUVpQixNQUFNQSxJQUFSLEVBQWIsRUFBNkIsTUFBN0IsRUFBcUNGLFFBQXJDO0FBQ0Q7Ozs7OztrQkFHWWIsVSIsImZpbGUiOiJIdHRwQ2xpZW50LmpzIiwic291cmNlc0NvbnRlbnQiOlsidmFyIGh0dHBzID0gcmVxdWlyZShcImh0dHBzXCIpO1xudmFyIGh0dHAgPSByZXF1aXJlKFwiaHR0cFwiKTtcbnZhciByZXF1ZXN0ID0gcmVxdWlyZShcInJlcXVlc3RcIik7XG52YXIgcXVlcnlzdHJpbmcgPSByZXF1aXJlKFwicXVlcnlzdHJpbmdcIik7XG5cbmNsYXNzIEh0dHBDbGllbnQge1xuICBjb25zdHJ1Y3RvcihvcHRpb25zLCBjcmVkZW50aWFscykge1xuICAgIHRoaXMuY3JlZGVudGlhbHMgPSBjcmVkZW50aWFscztcbiAgICB0aGlzLmhvc3QgPSBvcHRpb25zLmhvc3QgfHwgXCJyZXN0Lm5leG1vLmNvbVwiO1xuICAgIHRoaXMucG9ydCA9IG9wdGlvbnMucG9ydCB8fCA0NDM7XG4gICAgdGhpcy5odHRwcyA9IG9wdGlvbnMuaHR0cHMgfHwgaHR0cHM7XG4gICAgdGhpcy5odHRwID0gb3B0aW9ucy5odHRwIHx8IGh0dHA7XG4gICAgdGhpcy5oZWFkZXJzID0ge1xuICAgICAgXCJDb250ZW50LVR5cGVcIjogXCJhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWRcIixcbiAgICAgIEFjY2VwdDogXCJhcHBsaWNhdGlvbi9qc29uXCJcbiAgICB9O1xuICAgIHRoaXMubG9nZ2VyID0gb3B0aW9ucy5sb2dnZXI7XG4gICAgdGhpcy50aW1lb3V0ID0gb3B0aW9ucy50aW1lb3V0O1xuICAgIHRoaXMucmVxdWVzdExpYiA9IHJlcXVlc3Q7XG5cbiAgICBpZiAob3B0aW9ucy51c2VyQWdlbnQpIHtcbiAgICAgIHRoaXMuaGVhZGVyc1tcIlVzZXItQWdlbnRcIl0gPSBvcHRpb25zLnVzZXJBZ2VudDtcbiAgICB9XG4gIH1cblxuICByZXF1ZXN0KGVuZHBvaW50LCBtZXRob2QsIGNhbGxiYWNrLCBza2lwSnNvblBhcnNpbmcgPSBmYWxzZSkge1xuICAgIGlmICh0eXBlb2YgbWV0aG9kID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgIGNhbGxiYWNrID0gbWV0aG9kO1xuICAgICAgZW5kcG9pbnQubWV0aG9kID0gZW5kcG9pbnQubWV0aG9kIHx8IFwiR0VUXCI7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgbWV0aG9kICE9PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICBlbmRwb2ludC5tZXRob2QgPSBtZXRob2Q7XG4gICAgfVxuXG4gICAgaWYgKGVuZHBvaW50Lm1ldGhvZCA9PT0gXCJQT1NUXCIgfHwgZW5kcG9pbnQubWV0aG9kID09PSBcIkRFTEVURVwiKSB7XG4gICAgICAvLyBUT0RPOiB2ZXJpZnkgdGhlIGZvbGxvd2luZyBmaXggaXMgcmVxdWlyZWRcbiAgICAgIC8vIEZpeCBicm9rZW4gZHVlIG90IDQxMSBDb250ZW50LUxlbmd0aCBlcnJvciBub3cgc2VudCBieSBOZXhtbyBBUElcbiAgICAgIC8vIFBMIDIwMTYtU2VwdC02IC0gY29tbWVudGVkIG91dCBDb250ZW50LUxlbmd0aCAwXG4gICAgICAvLyBoZWFkZXJzWydDb250ZW50LUxlbmd0aCddID0gMDtcbiAgICB9XG4gICAgdmFyIG9wdGlvbnMgPSB7XG4gICAgICBob3N0OiBlbmRwb2ludC5ob3N0ID8gZW5kcG9pbnQuaG9zdCA6IHRoaXMuaG9zdCxcbiAgICAgIHBvcnQ6IHRoaXMucG9ydCxcbiAgICAgIHBhdGg6IGVuZHBvaW50LnBhdGgsXG4gICAgICBtZXRob2Q6IGVuZHBvaW50Lm1ldGhvZCxcbiAgICAgIGhlYWRlcnM6IE9iamVjdC5hc3NpZ24oe30sIHRoaXMuaGVhZGVycylcbiAgICB9O1xuXG4gICAgaWYgKHRoaXMudGltZW91dCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBvcHRpb25zLnRpbWVvdXQgPSB0aGlzLnRpbWVvdXQ7XG4gICAgfVxuXG4gICAgLy8gQWxsb3cgZXhpc3RpbmcgaGVhZGVycyB0byBiZSBvdmVycmlkZGVuXG4gICAgLy8gQWxsb3cgbmV3IGhlYWRlcnMgdG8gYmUgYWRkZWRcbiAgICBpZiAoZW5kcG9pbnQuaGVhZGVycykge1xuICAgICAgT2JqZWN0LmtleXMoZW5kcG9pbnQuaGVhZGVycykuZm9yRWFjaChmdW5jdGlvbihrZXkpIHtcbiAgICAgICAgb3B0aW9ucy5oZWFkZXJzW2tleV0gPSBlbmRwb2ludC5oZWFkZXJzW2tleV07XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICB0aGlzLmxvZ2dlci5pbmZvKFwiUmVxdWVzdDpcIiwgb3B0aW9ucywgXCJcXG5Cb2R5OlwiLCBlbmRwb2ludC5ib2R5KTtcbiAgICB2YXIgcmVxdWVzdDtcblxuICAgIGlmIChvcHRpb25zLnBvcnQgPT09IDQ0Mykge1xuICAgICAgcmVxdWVzdCA9IHRoaXMuaHR0cHMucmVxdWVzdChvcHRpb25zKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmVxdWVzdCA9IHRoaXMuaHR0cC5yZXF1ZXN0KG9wdGlvbnMpO1xuICAgIH1cblxuICAgIHJlcXVlc3QuZW5kKGVuZHBvaW50LmJvZHkpO1xuXG4gICAgLy8gS2VlcCBhbiBhcnJheSBvZiBTdHJpbmcgb3IgQnVmZmVycyxcbiAgICAvLyBkZXBlbmRpbmcgb24gY29udGVudCB0eXBlIChiaW5hcnkgb3IgSlNPTikgb2YgcmVzcG9uc2VcbiAgICB2YXIgcmVzcG9uc2VEYXRhID0gW107XG5cbiAgICByZXF1ZXN0Lm9uKFwicmVzcG9uc2VcIiwgcmVzcG9uc2UgPT4ge1xuICAgICAgdmFyIGlzQmluYXJ5ID1cbiAgICAgICAgcmVzcG9uc2UuaGVhZGVyc1tcImNvbnRlbnQtdHlwZVwiXSA9PT0gXCJhcHBsaWNhdGlvbi9vY3RldC1zdHJlYW1cIjtcbiAgICAgIGlmICghaXNCaW5hcnkpIHtcbiAgICAgICAgcmVzcG9uc2Uuc2V0RW5jb2RpbmcoXCJ1dGY4XCIpO1xuICAgICAgfVxuXG4gICAgICByZXNwb25zZS5vbihcImRhdGFcIiwgY2h1bmsgPT4ge1xuICAgICAgICByZXNwb25zZURhdGEucHVzaChjaHVuayk7XG4gICAgICB9KTtcblxuICAgICAgcmVzcG9uc2Uub24oXCJlbmRcIiwgKCkgPT4ge1xuICAgICAgICB0aGlzLmxvZ2dlci5pbmZvKFwicmVzcG9uc2UgZW5kZWQ6XCIsIHJlc3BvbnNlLnN0YXR1c0NvZGUpO1xuICAgICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgICBpZiAoaXNCaW5hcnkpIHtcbiAgICAgICAgICAgIHJlc3BvbnNlRGF0YSA9IEJ1ZmZlci5jb25jYXQocmVzcG9uc2VEYXRhKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICB0aGlzLl9fcGFyc2VSZXNwb25zZShcbiAgICAgICAgICAgIHJlc3BvbnNlLFxuICAgICAgICAgICAgcmVzcG9uc2VEYXRhLFxuICAgICAgICAgICAgZW5kcG9pbnQubWV0aG9kLFxuICAgICAgICAgICAgY2FsbGJhY2ssXG4gICAgICAgICAgICBza2lwSnNvblBhcnNpbmdcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHJlc3BvbnNlLm9uKFwiY2xvc2VcIiwgZSA9PiB7XG4gICAgICAgIGlmIChlKSB7XG4gICAgICAgICAgdGhpcy5sb2dnZXIuZXJyb3IoXG4gICAgICAgICAgICBcInByb2JsZW0gd2l0aCBBUEkgcmVxdWVzdCBkZXRhaWxlZCBzdGFja3RyYWNlIGJlbG93IFwiXG4gICAgICAgICAgKTtcbiAgICAgICAgICB0aGlzLmxvZ2dlci5lcnJvcihlKTtcbiAgICAgICAgICBjYWxsYmFjayhlKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSk7XG4gICAgcmVxdWVzdC5vbihcImVycm9yXCIsIGUgPT4ge1xuICAgICAgdGhpcy5sb2dnZXIuZXJyb3IoXCJwcm9ibGVtIHdpdGggQVBJIHJlcXVlc3QgZGV0YWlsZWQgc3RhY2t0cmFjZSBiZWxvdyBcIik7XG4gICAgICB0aGlzLmxvZ2dlci5lcnJvcihlKTtcbiAgICAgIGNhbGxiYWNrKGUpO1xuICAgIH0pO1xuICB9XG5cbiAgX19wYXJzZVJlc3BvbnNlKGh0dHBSZXNwb25zZSwgZGF0YSwgbWV0aG9kLCBjYWxsYmFjaywgc2tpcEpzb25QYXJzaW5nKSB7XG4gICAgY29uc3QgaXNBcnJheU9yQnVmZmVyID0gZGF0YSBpbnN0YW5jZW9mIEFycmF5IHx8IGRhdGEgaW5zdGFuY2VvZiBCdWZmZXI7XG4gICAgaWYgKCFpc0FycmF5T3JCdWZmZXIpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcImRhdGEgc2hvdWxkIGJlIG9mIHR5cGUgQXJyYXkgb3IgQnVmZmVyXCIpO1xuICAgIH1cblxuICAgIGNvbnN0IHN0YXR1cyA9IGh0dHBSZXNwb25zZS5zdGF0dXNDb2RlO1xuICAgIGNvbnN0IGhlYWRlcnMgPSBodHRwUmVzcG9uc2UuaGVhZGVycztcblxuICAgIGxldCByZXNwb25zZSA9IG51bGw7XG4gICAgdmFyIGVycm9yID0gbnVsbDtcblxuICAgIHRyeSB7XG4gICAgICBpZiAoc3RhdHVzID49IDUwMCkge1xuICAgICAgICBlcnJvciA9IHsgbWVzc2FnZTogXCJTZXJ2ZXIgRXJyb3JcIiwgc3RhdHVzQ29kZTogc3RhdHVzIH07XG4gICAgICB9IGVsc2UgaWYgKFxuICAgICAgICBodHRwUmVzcG9uc2UuaGVhZGVyc1tcImNvbnRlbnQtdHlwZVwiXSA9PT0gXCJhcHBsaWNhdGlvbi9vY3RldC1zdHJlYW1cIlxuICAgICAgKSB7XG4gICAgICAgIHJlc3BvbnNlID0gZGF0YTtcbiAgICAgIH0gZWxzZSBpZiAoc3RhdHVzID09PSA0MjkpIHtcbiAgICAgICAgLy8gNDI5IGRvZXMgbm90IHJldHVybiBhIHBhcnNhYmxlIGJvZHlcbiAgICAgICAgaWYgKCFoZWFkZXJzW1wicmV0cnktYWZ0ZXJcIl0pIHtcbiAgICAgICAgICAvLyByZXRyeSBiYXNlZCBvbiBhbGxvd2VkIHBlciBzZWNvbmRcbiAgICAgICAgICBjb25zdCByZXRyeUFmdGVyTWlsbGlzID0gbWV0aG9kID09PSBcIlBPU1RcIiA/IDEwMDAgLyAyIDogMTAwMCAvIDU7XG4gICAgICAgICAgaGVhZGVyc1tcInJldHJ5LWFmdGVyXCJdID0gcmV0cnlBZnRlck1pbGxpcztcbiAgICAgICAgfVxuICAgICAgICBlcnJvciA9IHsgYm9keTogZGF0YS5qb2luKFwiXCIpIH07XG4gICAgICB9IGVsc2UgaWYgKHN0YXR1cyA9PT0gMjA0KSB7XG4gICAgICAgIHJlc3BvbnNlID0gbnVsbDtcbiAgICAgIH0gZWxzZSBpZiAoc3RhdHVzID49IDQwMCB8fCBzdGF0dXMgPCAyMDApIHtcbiAgICAgICAgZXJyb3IgPSB7IGJvZHk6IEpTT04ucGFyc2UoZGF0YS5qb2luKFwiXCIpKSwgaGVhZGVycyB9O1xuICAgICAgfSBlbHNlIGlmIChtZXRob2QgIT09IFwiREVMRVRFXCIpIHtcbiAgICAgICAgaWYgKCEhc2tpcEpzb25QYXJzaW5nKSB7XG4gICAgICAgICAgcmVzcG9uc2UgPSBkYXRhLmpvaW4oXCJcIik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmVzcG9uc2UgPSBKU09OLnBhcnNlKGRhdGEuam9pbihcIlwiKSk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJlc3BvbnNlID0gZGF0YTtcbiAgICAgIH1cbiAgICB9IGNhdGNoIChwYXJzZUVycm9yKSB7XG4gICAgICB0aGlzLmxvZ2dlci5lcnJvcihwYXJzZUVycm9yKTtcbiAgICAgIHRoaXMubG9nZ2VyLmVycm9yKFxuICAgICAgICBcImNvdWxkIG5vdCBjb252ZXJ0IEFQSSByZXNwb25zZSB0byBKU09OLCBhYm92ZSBlcnJvciBpcyBpZ25vcmVkIGFuZCByYXcgQVBJIHJlc3BvbnNlIGlzIHJldHVybmVkIHRvIGNsaWVudFwiXG4gICAgICApO1xuICAgICAgdGhpcy5sb2dnZXIuZXJyb3IoXCJSYXcgRXJyb3IgbWVzc2FnZSBmcm9tIEFQSSBcIik7XG4gICAgICB0aGlzLmxvZ2dlci5lcnJvcihgXCIke2RhdGF9XCJgKTtcblxuICAgICAgZXJyb3IgPSB7XG4gICAgICAgIHN0YXR1czogc3RhdHVzLFxuICAgICAgICBtZXNzYWdlOiBcIlRoZSBBUEkgcmVzcG9uc2UgY291bGQgbm90IGJlIHBhcnNlZC5cIixcbiAgICAgICAgYm9keTogZGF0YS5qb2luKFwiXCIpLFxuICAgICAgICBwYXJzZUVycm9yOiBwYXJzZUVycm9yXG4gICAgICB9O1xuICAgIH1cblxuICAgIGlmIChlcnJvcikge1xuICAgICAgZXJyb3Iuc3RhdHVzQ29kZSA9IHN0YXR1cztcbiAgICAgIGVycm9yLmhlYWRlcnMgPSBoZWFkZXJzO1xuICAgIH1cblxuICAgIGlmICh0eXBlb2YgY2FsbGJhY2sgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgY2FsbGJhY2soZXJyb3IsIHJlc3BvbnNlKTtcbiAgICB9XG4gIH1cblxuICBfYWRkTGltaXRlZEFjY2Vzc01lc3NhZ2VUb0Vycm9ycyhjYWxsYmFjaywgbGltaXRlZEFjY2Vzc1N0YXR1cykge1xuICAgIHJldHVybiBmdW5jdGlvbihlcnIsIGRhdGEpIHtcbiAgICAgIGlmIChlcnIgJiYgZXJyLnN0YXR1cyA9PSBsaW1pdGVkQWNjZXNzU3RhdHVzKSB7XG4gICAgICAgIGVyci5fSU5GT18gPVxuICAgICAgICAgIFwiVGhpcyBlbmRwb2ludCBtYXkgbmVlZCBhY3RpdmF0aW5nIG9uIHlvdXIgYWNjb3VudC4gUGxlYXNlIGVtYWlsIHN1cHBvcnRAbmV4bW8uY29tIGZvciBtb3JlIGluZm9ybWF0aW9uXCI7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBjYWxsYmFjayhlcnIsIGRhdGEpO1xuICAgIH07XG4gIH1cblxuICBnZXQocGF0aCwgcGFyYW1zLCBjYWxsYmFjaywgdXNlSnd0ID0gZmFsc2UpIHtcbiAgICBpZiAoIWNhbGxiYWNrKSB7XG4gICAgICBpZiAodHlwZW9mIHBhcmFtcyA9PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgY2FsbGJhY2sgPSBwYXJhbXM7XG4gICAgICAgIHBhcmFtcyA9IHt9O1xuICAgICAgfVxuICAgIH1cblxuICAgIHBhcmFtcyA9IHBhcmFtcyB8fCB7fTtcbiAgICBpZiAoIXVzZUp3dCkge1xuICAgICAgcGFyYW1zW1wiYXBpX2tleVwiXSA9IHRoaXMuY3JlZGVudGlhbHMuYXBpS2V5O1xuICAgICAgcGFyYW1zW1wiYXBpX3NlY3JldFwiXSA9IHRoaXMuY3JlZGVudGlhbHMuYXBpU2VjcmV0O1xuICAgIH1cblxuICAgIHBhdGggPSBwYXRoICsgXCI/XCIgKyBxdWVyeXN0cmluZy5zdHJpbmdpZnkocGFyYW1zKTtcblxuICAgIGNvbnN0IGhlYWRlcnMgPSB7IFwiQ29udGVudC1UeXBlXCI6IFwiYXBwbGljYXRpb24vanNvblwiIH07XG4gICAgaWYgKHVzZUp3dCkge1xuICAgICAgaGVhZGVyc1tcIkF1dGhvcml6YXRpb25cIl0gPSBgQmVhcmVyICR7dGhpcy5jcmVkZW50aWFscy5nZW5lcmF0ZUp3dCgpfWA7XG4gICAgfVxuXG4gICAgdGhpcy5yZXF1ZXN0KHsgcGF0aDogcGF0aCwgaGVhZGVycyB9LCBcIkdFVFwiLCBjYWxsYmFjayk7XG4gIH1cblxuICBkZWxldGUocGF0aCwgY2FsbGJhY2ssIHVzZUp3dCkge1xuICAgIGxldCBwYXJhbXMgPSB7fTtcbiAgICBpZiAoIXVzZUp3dCkge1xuICAgICAgcGFyYW1zW1wiYXBpX2tleVwiXSA9IHRoaXMuY3JlZGVudGlhbHMuYXBpS2V5O1xuICAgICAgcGFyYW1zW1wiYXBpX3NlY3JldFwiXSA9IHRoaXMuY3JlZGVudGlhbHMuYXBpU2VjcmV0O1xuICAgIH1cblxuICAgIHBhdGggPSBwYXRoICsgXCI/XCIgKyBxdWVyeXN0cmluZy5zdHJpbmdpZnkocGFyYW1zKTtcblxuICAgIHRoaXMucmVxdWVzdCh7IHBhdGg6IHBhdGggfSwgXCJERUxFVEVcIiwgY2FsbGJhY2spO1xuICB9XG5cbiAgcG9zdEZpbGUocGF0aCwgb3B0aW9ucywgY2FsbGJhY2ssIHVzZUp3dCkge1xuICAgIGxldCBxcyA9IHt9O1xuICAgIGlmICghdXNlSnd0KSB7XG4gICAgICBxc1tcImFwaV9rZXlcIl0gPSB0aGlzLmNyZWRlbnRpYWxzLmFwaUtleTtcbiAgICAgIHFzW1wiYXBpX3NlY3JldFwiXSA9IHRoaXMuY3JlZGVudGlhbHMuYXBpU2VjcmV0O1xuICAgIH1cblxuICAgIGlmIChPYmplY3Qua2V5cyhxcykubGVuZ3RoKSB7XG4gICAgICBsZXQgam9pbkNoYXIgPSBcIj9cIjtcbiAgICAgIGlmIChwYXRoLmluZGV4T2Yoam9pbkNoYXIpICE9PSAtMSkge1xuICAgICAgICBqb2luQ2hhciA9IFwiJlwiO1xuICAgICAgfVxuICAgICAgcGF0aCA9IHBhdGggKyBqb2luQ2hhciArIHF1ZXJ5c3RyaW5nLnN0cmluZ2lmeShxcyk7XG4gICAgfVxuXG4gICAgY29uc3QgZmlsZSA9IG9wdGlvbnMuZmlsZTtcbiAgICBkZWxldGUgb3B0aW9ucy5maWxlOyAvLyBXZSBkb24ndCBzZW5kIHRoaXMgYXMgbWV0YWRhdGFcblxuICAgIGNvbnN0IGZvcm1EYXRhID0ge307XG5cbiAgICBpZiAoZmlsZSkge1xuICAgICAgZm9ybURhdGFbXCJmaWxlZGF0YVwiXSA9IHtcbiAgICAgICAgdmFsdWU6IGZpbGUsXG4gICAgICAgIG9wdGlvbnM6IHtcbiAgICAgICAgICBmaWxlbmFtZTogb3B0aW9ucy5maWxlbmFtZSB8fCBudWxsXG4gICAgICAgIH1cbiAgICAgIH07XG4gICAgfVxuXG4gICAgaWYgKG9wdGlvbnMuaW5mbykge1xuICAgICAgZm9ybURhdGEuaW5mbyA9IEpTT04uc3RyaW5naWZ5KG9wdGlvbnMuaW5mbyk7XG4gICAgfVxuXG4gICAgaWYgKG9wdGlvbnMudXJsKSB7XG4gICAgICBmb3JtRGF0YS51cmwgPSBvcHRpb25zLnVybDtcbiAgICB9XG5cbiAgICB0aGlzLnJlcXVlc3RMaWIucG9zdChcbiAgICAgIHtcbiAgICAgICAgdXJsOiBcImh0dHBzOi8vXCIgKyB0aGlzLmhvc3QgKyBwYXRoLFxuICAgICAgICBmb3JtRGF0YTogZm9ybURhdGEsXG4gICAgICAgIGhlYWRlcnM6IHtcbiAgICAgICAgICBBdXRob3JpemF0aW9uOiBgQmVhcmVyICR7dGhpcy5jcmVkZW50aWFscy5nZW5lcmF0ZUp3dCgpfWBcbiAgICAgICAgfVxuICAgICAgfSxcbiAgICAgIGNhbGxiYWNrXG4gICAgKTtcbiAgfVxuXG4gIHBvc3QocGF0aCwgcGFyYW1zLCBjYWxsYmFjaywgdXNlSnd0KSB7XG4gICAgbGV0IHFzID0ge307XG4gICAgaWYgKCF1c2VKd3QpIHtcbiAgICAgIHFzW1wiYXBpX2tleVwiXSA9IHRoaXMuY3JlZGVudGlhbHMuYXBpS2V5O1xuICAgICAgcXNbXCJhcGlfc2VjcmV0XCJdID0gdGhpcy5jcmVkZW50aWFscy5hcGlTZWNyZXQ7XG4gICAgfVxuXG4gICAgbGV0IGpvaW5DaGFyID0gXCI/XCI7XG4gICAgaWYgKHBhdGguaW5kZXhPZihqb2luQ2hhcikgIT09IC0xKSB7XG4gICAgICBqb2luQ2hhciA9IFwiJlwiO1xuICAgIH1cblxuICAgIHBhdGggPSBwYXRoICsgam9pbkNoYXIgKyBxdWVyeXN0cmluZy5zdHJpbmdpZnkocXMpO1xuXG4gICAgdGhpcy5yZXF1ZXN0KFxuICAgICAgeyBwYXRoOiBwYXRoLCBib2R5OiBxdWVyeXN0cmluZy5zdHJpbmdpZnkocGFyYW1zKSB9LFxuICAgICAgXCJQT1NUXCIsXG4gICAgICBjYWxsYmFja1xuICAgICk7XG4gIH1cblxuICBwb3N0SnNvbihwYXRoLCBwYXJhbXMsIGNhbGxiYWNrLCB1c2VKd3QpIHtcbiAgICBsZXQgcXMgPSB7fTtcbiAgICBpZiAoIXVzZUp3dCkge1xuICAgICAgcXNbXCJhcGlfa2V5XCJdID0gdGhpcy5jcmVkZW50aWFscy5hcGlLZXk7XG4gICAgICBxc1tcImFwaV9zZWNyZXRcIl0gPSB0aGlzLmNyZWRlbnRpYWxzLmFwaVNlY3JldDtcbiAgICB9XG5cbiAgICBsZXQgam9pbkNoYXIgPSBcIj9cIjtcbiAgICBpZiAocGF0aC5pbmRleE9mKGpvaW5DaGFyKSAhPT0gLTEpIHtcbiAgICAgIGpvaW5DaGFyID0gXCImXCI7XG4gICAgfVxuXG4gICAgcGF0aCA9IHBhdGggKyBqb2luQ2hhciArIHF1ZXJ5c3RyaW5nLnN0cmluZ2lmeShxcyk7XG5cbiAgICB0aGlzLnJlcXVlc3QoXG4gICAgICB7XG4gICAgICAgIHBhdGg6IHBhdGgsXG4gICAgICAgIGJvZHk6IEpTT04uc3RyaW5naWZ5KHBhcmFtcyksXG4gICAgICAgIGhlYWRlcnM6IHsgXCJDb250ZW50LVR5cGVcIjogXCJhcHBsaWNhdGlvbi9qc29uXCIgfVxuICAgICAgfSxcbiAgICAgIFwiUE9TVFwiLFxuICAgICAgY2FsbGJhY2tcbiAgICApO1xuICB9XG5cbiAgcG9zdFVzZVF1ZXJ5U3RyaW5nKHBhdGgsIHBhcmFtcywgY2FsbGJhY2ssIHVzZUp3dCkge1xuICAgIHBhcmFtcyA9IHBhcmFtcyB8fCB7fTtcbiAgICBpZiAoIXVzZUp3dCkge1xuICAgICAgcGFyYW1zW1wiYXBpX2tleVwiXSA9IHRoaXMuY3JlZGVudGlhbHMuYXBpS2V5O1xuICAgICAgcGFyYW1zW1wiYXBpX3NlY3JldFwiXSA9IHRoaXMuY3JlZGVudGlhbHMuYXBpU2VjcmV0O1xuICAgIH1cblxuICAgIHBhdGggPSBwYXRoICsgXCI/XCIgKyBxdWVyeXN0cmluZy5zdHJpbmdpZnkocGFyYW1zKTtcblxuICAgIHRoaXMucmVxdWVzdCh7IHBhdGg6IHBhdGggfSwgXCJQT1NUXCIsIGNhbGxiYWNrKTtcbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBIdHRwQ2xpZW50O1xuIl19 |
\ | No newline at end of file |