@appium/base-driver 8.7.3 → 9.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/lib/basedriver/capabilities.d.ts +11 -163
- package/build/lib/basedriver/capabilities.d.ts.map +1 -1
- package/build/lib/basedriver/capabilities.js +354 -236
- package/build/lib/basedriver/capabilities.js.map +1 -1
- package/build/lib/basedriver/commands/event.d.ts +7 -6
- package/build/lib/basedriver/commands/event.d.ts.map +1 -1
- package/build/lib/basedriver/commands/event.js +55 -35
- package/build/lib/basedriver/commands/event.js.map +1 -1
- package/build/lib/basedriver/commands/execute.d.ts +7 -6
- package/build/lib/basedriver/commands/execute.d.ts.map +1 -1
- package/build/lib/basedriver/commands/execute.js +66 -58
- package/build/lib/basedriver/commands/execute.js.map +1 -1
- package/build/lib/basedriver/commands/find.d.ts +9 -7
- package/build/lib/basedriver/commands/find.d.ts.map +1 -1
- package/build/lib/basedriver/commands/find.js +102 -54
- package/build/lib/basedriver/commands/find.js.map +1 -1
- package/build/lib/basedriver/commands/index.d.ts +3 -7
- package/build/lib/basedriver/commands/index.d.ts.map +1 -1
- package/build/lib/basedriver/commands/index.js +30 -33
- package/build/lib/basedriver/commands/index.js.map +1 -1
- package/build/lib/basedriver/commands/log.d.ts +8 -9
- package/build/lib/basedriver/commands/log.d.ts.map +1 -1
- package/build/lib/basedriver/commands/log.js +54 -38
- package/build/lib/basedriver/commands/log.js.map +1 -1
- package/build/lib/basedriver/commands/session.d.ts +7 -6
- package/build/lib/basedriver/commands/session.d.ts.map +1 -1
- package/build/lib/basedriver/commands/session.js +46 -39
- package/build/lib/basedriver/commands/session.js.map +1 -1
- package/build/lib/basedriver/commands/settings.d.ts +7 -7
- package/build/lib/basedriver/commands/settings.d.ts.map +1 -1
- package/build/lib/basedriver/commands/settings.js +35 -28
- package/build/lib/basedriver/commands/settings.js.map +1 -1
- package/build/lib/basedriver/commands/timeout.d.ts +7 -5
- package/build/lib/basedriver/commands/timeout.d.ts.map +1 -1
- package/build/lib/basedriver/commands/timeout.js +144 -162
- package/build/lib/basedriver/commands/timeout.js.map +1 -1
- package/build/lib/basedriver/core.d.ts +6 -157
- package/build/lib/basedriver/core.d.ts.map +1 -1
- package/build/lib/basedriver/core.js +361 -230
- package/build/lib/basedriver/core.js.map +1 -1
- package/build/lib/basedriver/desired-caps.js +80 -110
- package/build/lib/basedriver/desired-caps.js.map +1 -1
- package/build/lib/basedriver/device-settings.js +57 -62
- package/build/lib/basedriver/device-settings.js.map +1 -1
- package/build/lib/basedriver/driver.d.ts +11 -262
- package/build/lib/basedriver/driver.d.ts.map +1 -1
- package/build/lib/basedriver/driver.js +362 -262
- package/build/lib/basedriver/driver.js.map +1 -1
- package/build/lib/basedriver/helpers.js +500 -495
- package/build/lib/basedriver/helpers.js.map +1 -1
- package/build/lib/basedriver/logger.d.ts +1 -1
- package/build/lib/basedriver/logger.d.ts.map +1 -1
- package/build/lib/basedriver/logger.js +5 -15
- package/build/lib/basedriver/logger.js.map +1 -1
- package/build/lib/constants.js +14 -14
- package/build/lib/constants.js.map +1 -1
- package/build/lib/express/crash.js +8 -15
- package/build/lib/express/crash.js.map +1 -1
- package/build/lib/express/express-logging.js +49 -59
- package/build/lib/express/express-logging.js.map +1 -1
- package/build/lib/express/idempotency.js +125 -177
- package/build/lib/express/idempotency.js.map +1 -1
- package/build/lib/express/logger.d.ts +1 -1
- package/build/lib/express/logger.d.ts.map +1 -1
- package/build/lib/express/logger.js +5 -15
- package/build/lib/express/logger.js.map +1 -1
- package/build/lib/express/middleware.js +82 -107
- package/build/lib/express/middleware.js.map +1 -1
- package/build/lib/express/server.d.ts +17 -5
- package/build/lib/express/server.d.ts.map +1 -1
- package/build/lib/express/server.js +259 -224
- package/build/lib/express/server.js.map +1 -1
- package/build/lib/express/static.js +64 -81
- package/build/lib/express/static.js.map +1 -1
- package/build/lib/express/websocket.js +115 -87
- package/build/lib/express/websocket.js.map +1 -1
- package/build/lib/helpers/capabilities.d.ts +1 -59
- package/build/lib/helpers/capabilities.d.ts.map +1 -1
- package/build/lib/helpers/capabilities.js +72 -69
- package/build/lib/helpers/capabilities.js.map +1 -1
- package/build/lib/index.js +64 -180
- package/build/lib/index.js.map +1 -1
- package/build/lib/jsonwp-proxy/protocol-converter.js +215 -227
- package/build/lib/jsonwp-proxy/protocol-converter.js.map +1 -1
- package/build/lib/jsonwp-proxy/proxy.d.ts.map +1 -1
- package/build/lib/jsonwp-proxy/proxy.js +355 -393
- package/build/lib/jsonwp-proxy/proxy.js.map +1 -1
- package/build/lib/jsonwp-status/status.js +119 -130
- package/build/lib/jsonwp-status/status.js.map +1 -1
- package/build/lib/protocol/errors.d.ts +135 -32
- package/build/lib/protocol/errors.d.ts.map +1 -1
- package/build/lib/protocol/errors.js +871 -919
- package/build/lib/protocol/errors.js.map +1 -1
- package/build/lib/protocol/helpers.js +37 -37
- package/build/lib/protocol/helpers.js.map +1 -1
- package/build/lib/protocol/index.js +22 -109
- package/build/lib/protocol/index.js.map +1 -1
- package/build/lib/protocol/protocol.js +394 -350
- package/build/lib/protocol/protocol.js.map +1 -1
- package/build/lib/protocol/routes.d.ts +1238 -4
- package/build/lib/protocol/routes.d.ts.map +1 -1
- package/build/lib/protocol/routes.js +964 -1327
- package/build/lib/protocol/routes.js.map +1 -1
- package/build/lib/protocol/validators.js +32 -39
- package/build/lib/protocol/validators.js.map +1 -1
- package/build/tsconfig.tsbuildinfo +1 -1
- package/lib/basedriver/capabilities.js +80 -39
- package/lib/basedriver/commands/event.js +10 -5
- package/lib/basedriver/commands/execute.js +14 -9
- package/lib/basedriver/commands/find.js +18 -12
- package/lib/basedriver/commands/index.js +21 -16
- package/lib/basedriver/commands/log.js +24 -18
- package/lib/basedriver/commands/session.js +10 -5
- package/lib/basedriver/commands/settings.js +9 -6
- package/lib/basedriver/commands/timeout.js +10 -4
- package/lib/basedriver/core.js +2 -3
- package/lib/basedriver/driver.js +12 -16
- package/lib/express/server.js +6 -3
- package/lib/protocol/errors.js +155 -44
- package/lib/protocol/routes.js +11 -7
- package/package.json +14 -16
|
@@ -1,419 +1,381 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
});
|
|
6
|
-
exports.
|
|
7
|
-
|
|
8
|
-
require("
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
var _protocol = require("../protocol");
|
|
21
|
-
|
|
22
|
-
var _constants = require("../constants");
|
|
23
|
-
|
|
24
|
-
var _protocolConverter = _interopRequireDefault(require("./protocol-converter"));
|
|
25
|
-
|
|
26
|
-
var _helpers = require("../protocol/helpers");
|
|
27
|
-
|
|
28
|
-
var _http = _interopRequireDefault(require("http"));
|
|
29
|
-
|
|
30
|
-
var _https = _interopRequireDefault(require("https"));
|
|
31
|
-
|
|
32
|
-
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
33
|
-
|
|
34
|
-
const DEFAULT_LOG = _support.logger.getLogger('WD Proxy');
|
|
35
|
-
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.JWProxy = void 0;
|
|
7
|
+
const lodash_1 = __importDefault(require("lodash"));
|
|
8
|
+
const support_1 = require("@appium/support");
|
|
9
|
+
const axios_1 = __importDefault(require("axios"));
|
|
10
|
+
const status_1 = require("../jsonwp-status/status");
|
|
11
|
+
const errors_1 = require("../protocol/errors");
|
|
12
|
+
const protocol_1 = require("../protocol");
|
|
13
|
+
const constants_1 = require("../constants");
|
|
14
|
+
const protocol_converter_1 = __importDefault(require("./protocol-converter"));
|
|
15
|
+
const helpers_1 = require("../protocol/helpers");
|
|
16
|
+
const http_1 = __importDefault(require("http"));
|
|
17
|
+
const https_1 = __importDefault(require("https"));
|
|
18
|
+
const DEFAULT_LOG = support_1.logger.getLogger('WD Proxy');
|
|
36
19
|
const DEFAULT_REQUEST_TIMEOUT = 240000;
|
|
37
20
|
const COMPACT_ERROR_PATTERNS = [/\bECONNREFUSED\b/, /socket hang up/];
|
|
38
|
-
const {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
21
|
+
const { MJSONWP, W3C } = constants_1.PROTOCOLS;
|
|
22
|
+
const ALLOWED_OPTS = [
|
|
23
|
+
'scheme',
|
|
24
|
+
'server',
|
|
25
|
+
'port',
|
|
26
|
+
'base',
|
|
27
|
+
'reqBasePath',
|
|
28
|
+
'sessionId',
|
|
29
|
+
'timeout',
|
|
30
|
+
'log',
|
|
31
|
+
'keepAlive',
|
|
32
|
+
];
|
|
44
33
|
class JWProxy {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
keepAlive: opts.keepAlive ?? true,
|
|
72
|
-
maxSockets: 10,
|
|
73
|
-
maxFreeSockets: 5
|
|
74
|
-
};
|
|
75
|
-
this.httpAgent = new _http.default.Agent(agentOpts);
|
|
76
|
-
this.httpsAgent = new _https.default.Agent(agentOpts);
|
|
77
|
-
this.protocolConverter = new _protocolConverter.default(this.proxy.bind(this), opts.log);
|
|
78
|
-
this._log = opts.log;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
get log() {
|
|
82
|
-
return this._log ?? DEFAULT_LOG;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
async request(requestConfig) {
|
|
86
|
-
const reqPromise = (0, _axios.default)(requestConfig);
|
|
87
|
-
|
|
88
|
-
this._activeRequests.push(reqPromise);
|
|
89
|
-
|
|
90
|
-
try {
|
|
91
|
-
return await reqPromise;
|
|
92
|
-
} finally {
|
|
93
|
-
_lodash.default.pull(this._activeRequests, reqPromise);
|
|
34
|
+
constructor(opts = {}) {
|
|
35
|
+
opts = lodash_1.default.pick(opts, ALLOWED_OPTS);
|
|
36
|
+
// omit 'log' in the defaults assignment here because 'log' is a getter and we are going to set
|
|
37
|
+
// it to this._log (which lies behind the getter) further down
|
|
38
|
+
const options = lodash_1.default.defaults(lodash_1.default.omit(opts, 'log'), {
|
|
39
|
+
scheme: 'http',
|
|
40
|
+
server: 'localhost',
|
|
41
|
+
port: 4444,
|
|
42
|
+
base: constants_1.DEFAULT_BASE_PATH,
|
|
43
|
+
reqBasePath: constants_1.DEFAULT_BASE_PATH,
|
|
44
|
+
sessionId: null,
|
|
45
|
+
timeout: DEFAULT_REQUEST_TIMEOUT,
|
|
46
|
+
});
|
|
47
|
+
options.scheme = options.scheme.toLowerCase();
|
|
48
|
+
Object.assign(this, options);
|
|
49
|
+
this._activeRequests = [];
|
|
50
|
+
this._downstreamProtocol = null;
|
|
51
|
+
const agentOpts = {
|
|
52
|
+
keepAlive: opts.keepAlive ?? true,
|
|
53
|
+
maxSockets: 10,
|
|
54
|
+
maxFreeSockets: 5,
|
|
55
|
+
};
|
|
56
|
+
this.httpAgent = new http_1.default.Agent(agentOpts);
|
|
57
|
+
this.httpsAgent = new https_1.default.Agent(agentOpts);
|
|
58
|
+
this.protocolConverter = new protocol_converter_1.default(this.proxy.bind(this), opts.log);
|
|
59
|
+
this._log = opts.log;
|
|
94
60
|
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
getActiveRequestsCount() {
|
|
98
|
-
return this._activeRequests.length;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
cancelActiveRequests() {
|
|
102
|
-
this._activeRequests = [];
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
endpointRequiresSessionId(endpoint) {
|
|
106
|
-
return !_lodash.default.includes(['/session', '/sessions', '/status'], endpoint);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
set downstreamProtocol(value) {
|
|
110
|
-
this._downstreamProtocol = value;
|
|
111
|
-
this.protocolConverter.downstreamProtocol = value;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
get downstreamProtocol() {
|
|
115
|
-
return this._downstreamProtocol;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
getUrlForProxy(url) {
|
|
119
|
-
if (url === '') {
|
|
120
|
-
url = '/';
|
|
61
|
+
get log() {
|
|
62
|
+
return this._log ?? DEFAULT_LOG;
|
|
121
63
|
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
64
|
+
/**
|
|
65
|
+
* Performs requests to the downstream server
|
|
66
|
+
*
|
|
67
|
+
* @private - Do not call this method directly,
|
|
68
|
+
* it uses client-specific arguments and responses!
|
|
69
|
+
*
|
|
70
|
+
* @param {import('axios').AxiosRequestConfig} requestConfig
|
|
71
|
+
* @returns {Promise<import('axios').AxiosResponse>}
|
|
72
|
+
*/
|
|
73
|
+
async request(requestConfig) {
|
|
74
|
+
const reqPromise = (0, axios_1.default)(requestConfig);
|
|
75
|
+
this._activeRequests.push(reqPromise);
|
|
76
|
+
try {
|
|
77
|
+
return await reqPromise;
|
|
78
|
+
}
|
|
79
|
+
finally {
|
|
80
|
+
lodash_1.default.pull(this._activeRequests, reqPromise);
|
|
81
|
+
}
|
|
139
82
|
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
if (stripPrefixRe.test(remainingUrl)) {
|
|
144
|
-
remainingUrl = stripPrefixRe.exec(remainingUrl)[1];
|
|
83
|
+
getActiveRequestsCount() {
|
|
84
|
+
return this._activeRequests.length;
|
|
145
85
|
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
remainingUrl = `/session/${this.sessionId}${remainingUrl}`;
|
|
86
|
+
cancelActiveRequests() {
|
|
87
|
+
this._activeRequests = [];
|
|
149
88
|
}
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
if (requiresSessionId && this.sessionId === null) {
|
|
154
|
-
throw new Error('Trying to proxy a session command without session id');
|
|
89
|
+
endpointRequiresSessionId(endpoint) {
|
|
90
|
+
return !lodash_1.default.includes(['/session', '/sessions', '/status'], endpoint);
|
|
155
91
|
}
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
if (sessionBaseRe.test(remainingUrl)) {
|
|
160
|
-
if (this.sessionId === null) {
|
|
161
|
-
throw new ReferenceError(`Session ID is not set, but saw a URL path referencing a session (${remainingUrl}). This may be a bug in your client.`);
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
const match = sessionBaseRe.exec(remainingUrl);
|
|
165
|
-
remainingUrl = remainingUrl.replace(match[1], this.sessionId);
|
|
166
|
-
} else if (requiresSessionId) {
|
|
167
|
-
throw new Error(`Could not find :session section for url: ${remainingUrl}`);
|
|
92
|
+
set downstreamProtocol(value) {
|
|
93
|
+
this._downstreamProtocol = value;
|
|
94
|
+
this.protocolConverter.downstreamProtocol = value;
|
|
168
95
|
}
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
return proxyBase + remainingUrl;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
async proxy(url, method, body = null) {
|
|
175
|
-
method = method.toUpperCase();
|
|
176
|
-
const newUrl = this.getUrlForProxy(url);
|
|
177
|
-
|
|
178
|
-
const truncateBody = content => _lodash.default.truncate(_lodash.default.isString(content) ? content : JSON.stringify(content), {
|
|
179
|
-
length: _constants.MAX_LOG_BODY_LENGTH
|
|
180
|
-
});
|
|
181
|
-
|
|
182
|
-
const reqOpts = {
|
|
183
|
-
url: newUrl,
|
|
184
|
-
method,
|
|
185
|
-
headers: {
|
|
186
|
-
'content-type': 'application/json; charset=utf-8',
|
|
187
|
-
'user-agent': 'appium',
|
|
188
|
-
accept: 'application/json, */*'
|
|
189
|
-
},
|
|
190
|
-
proxy: false,
|
|
191
|
-
timeout: this.timeout,
|
|
192
|
-
httpAgent: this.httpAgent,
|
|
193
|
-
httpsAgent: this.httpsAgent
|
|
194
|
-
};
|
|
195
|
-
|
|
196
|
-
if (_support.util.hasValue(body) && method !== 'GET') {
|
|
197
|
-
if (typeof body !== 'object') {
|
|
198
|
-
try {
|
|
199
|
-
reqOpts.data = JSON.parse(body);
|
|
200
|
-
} catch (e) {
|
|
201
|
-
throw new Error(`Cannot interpret the request body as valid JSON: ${truncateBody(body)}`);
|
|
202
|
-
}
|
|
203
|
-
} else {
|
|
204
|
-
reqOpts.data = body;
|
|
205
|
-
}
|
|
96
|
+
get downstreamProtocol() {
|
|
97
|
+
return this._downstreamProtocol;
|
|
206
98
|
}
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
const throwProxyError = error => {
|
|
211
|
-
const err = new Error(`The request to ${url} has failed`);
|
|
212
|
-
err.response = {
|
|
213
|
-
data: error,
|
|
214
|
-
status: 500
|
|
215
|
-
};
|
|
216
|
-
throw err;
|
|
217
|
-
};
|
|
218
|
-
|
|
219
|
-
let isResponseLogged = false;
|
|
220
|
-
|
|
221
|
-
try {
|
|
222
|
-
const {
|
|
223
|
-
data,
|
|
224
|
-
status,
|
|
225
|
-
headers
|
|
226
|
-
} = await this.request(reqOpts);
|
|
227
|
-
|
|
228
|
-
if (!_lodash.default.isPlainObject(data)) {
|
|
229
|
-
throwProxyError(data);
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
this.log.debug(`Got response with status ${status}: ${truncateBody(data)}`);
|
|
233
|
-
isResponseLogged = true;
|
|
234
|
-
const isSessionCreationRequest = /\/session$/.test(url) && method === 'POST';
|
|
235
|
-
|
|
236
|
-
if (isSessionCreationRequest) {
|
|
237
|
-
if (status === 200) {
|
|
238
|
-
this.sessionId = data.sessionId || (data.value || {}).sessionId;
|
|
99
|
+
getUrlForProxy(url) {
|
|
100
|
+
if (url === '') {
|
|
101
|
+
url = '/';
|
|
239
102
|
}
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
const res = {
|
|
250
|
-
statusCode: status,
|
|
251
|
-
headers,
|
|
252
|
-
body: data
|
|
253
|
-
};
|
|
254
|
-
return [res, data];
|
|
255
|
-
} catch (e) {
|
|
256
|
-
var _e$response, _e$response2;
|
|
257
|
-
|
|
258
|
-
let proxyErrorMsg = e.message;
|
|
259
|
-
|
|
260
|
-
if (_support.util.hasValue(e.response)) {
|
|
261
|
-
if (!isResponseLogged) {
|
|
262
|
-
const error = truncateBody(e.response.data);
|
|
263
|
-
this.log.info(_support.util.hasValue(e.response.status) ? `Got response with status ${e.response.status}: ${error}` : `Got response with unknown status: ${error}`);
|
|
103
|
+
const proxyBase = `${this.scheme}://${this.server}:${this.port}${this.base}`;
|
|
104
|
+
const endpointRe = '(/(session|status))';
|
|
105
|
+
let remainingUrl = '';
|
|
106
|
+
if (/^http/.test(url)) {
|
|
107
|
+
const first = new RegExp(`(https?://.+)${endpointRe}`).exec(url);
|
|
108
|
+
if (!first) {
|
|
109
|
+
throw new Error('Got a complete url but could not extract JWP endpoint');
|
|
110
|
+
}
|
|
111
|
+
remainingUrl = url.replace(first[1], '');
|
|
264
112
|
}
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
if (COMPACT_ERROR_PATTERNS.some(p => p.test(e.message))) {
|
|
269
|
-
this.log.info(e.message);
|
|
270
|
-
} else {
|
|
271
|
-
this.log.info(e.stack);
|
|
113
|
+
else if (new RegExp('^/').test(url)) {
|
|
114
|
+
remainingUrl = url;
|
|
272
115
|
}
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
116
|
+
else {
|
|
117
|
+
throw new Error(`Did not know what to do with url '${url}'`);
|
|
118
|
+
}
|
|
119
|
+
const stripPrefixRe = new RegExp('^.*?(/(session|status).*)$');
|
|
120
|
+
if (stripPrefixRe.test(remainingUrl)) {
|
|
121
|
+
remainingUrl = /** @type {RegExpExecArray} */ (stripPrefixRe.exec(remainingUrl))[1];
|
|
122
|
+
}
|
|
123
|
+
if (!new RegExp(endpointRe).test(remainingUrl)) {
|
|
124
|
+
remainingUrl = `/session/${this.sessionId}${remainingUrl}`;
|
|
125
|
+
}
|
|
126
|
+
const requiresSessionId = this.endpointRequiresSessionId(remainingUrl);
|
|
127
|
+
if (requiresSessionId && this.sessionId === null) {
|
|
128
|
+
throw new Error('Trying to proxy a session command without session id');
|
|
129
|
+
}
|
|
130
|
+
const sessionBaseRe = new RegExp('^/session/([^/]+)');
|
|
131
|
+
if (sessionBaseRe.test(remainingUrl)) {
|
|
132
|
+
if (this.sessionId === null) {
|
|
133
|
+
throw new ReferenceError(`Session ID is not set, but saw a URL path referencing a session (${remainingUrl}). This may be a bug in your client.`);
|
|
134
|
+
}
|
|
135
|
+
// we have something like /session/:id/foobar, so we need to replace
|
|
136
|
+
// the session id
|
|
137
|
+
const match = sessionBaseRe.exec(remainingUrl);
|
|
138
|
+
// TODO: if `requiresSessionId` is `false` and `sessionId` is `null`, this is a bug.
|
|
139
|
+
// are we sure `sessionId` is not `null`?
|
|
140
|
+
remainingUrl = remainingUrl.replace(
|
|
141
|
+
/** @type {RegExpExecArray} */ (match)[1],
|
|
142
|
+
/** @type {string} */ (this.sessionId));
|
|
143
|
+
}
|
|
144
|
+
else if (requiresSessionId) {
|
|
145
|
+
throw new Error(`Could not find :session section for url: ${remainingUrl}`);
|
|
146
|
+
}
|
|
147
|
+
remainingUrl = remainingUrl.replace(/\/$/, ''); // can't have trailing slashes
|
|
148
|
+
return proxyBase + remainingUrl;
|
|
302
149
|
}
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
150
|
+
async proxy(url, method, body = null) {
|
|
151
|
+
method = method.toUpperCase();
|
|
152
|
+
const newUrl = this.getUrlForProxy(url);
|
|
153
|
+
const truncateBody = (content) => lodash_1.default.truncate(lodash_1.default.isString(content) ? content : JSON.stringify(content), {
|
|
154
|
+
length: constants_1.MAX_LOG_BODY_LENGTH,
|
|
155
|
+
});
|
|
156
|
+
/** @type {import('axios').AxiosRequestConfig} */
|
|
157
|
+
const reqOpts = {
|
|
158
|
+
url: newUrl,
|
|
159
|
+
method,
|
|
160
|
+
headers: {
|
|
161
|
+
'content-type': 'application/json; charset=utf-8',
|
|
162
|
+
'user-agent': 'appium',
|
|
163
|
+
accept: 'application/json, */*',
|
|
164
|
+
},
|
|
165
|
+
proxy: false,
|
|
166
|
+
timeout: this.timeout,
|
|
167
|
+
httpAgent: this.httpAgent,
|
|
168
|
+
httpsAgent: this.httpsAgent,
|
|
169
|
+
};
|
|
170
|
+
// GET methods shouldn't have any body. Most servers are OK with this, but WebDriverAgent throws 400 errors
|
|
171
|
+
if (support_1.util.hasValue(body) && method !== 'GET') {
|
|
172
|
+
if (typeof body !== 'object') {
|
|
173
|
+
try {
|
|
174
|
+
reqOpts.data = JSON.parse(body);
|
|
175
|
+
}
|
|
176
|
+
catch (e) {
|
|
177
|
+
throw new Error(`Cannot interpret the request body as valid JSON: ${truncateBody(body)}`);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
reqOpts.data = body;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
this.log.debug(`Proxying [${method} ${url || '/'}] to [${method} ${newUrl}] ` +
|
|
185
|
+
(reqOpts.data ? `with body: ${truncateBody(reqOpts.data)}` : 'with no body'));
|
|
186
|
+
const throwProxyError = (error) => {
|
|
187
|
+
const err = /** @type {ProxyError} */ (new Error(`The request to ${url} has failed`));
|
|
188
|
+
err.response = {
|
|
189
|
+
data: error,
|
|
190
|
+
status: 500,
|
|
191
|
+
};
|
|
192
|
+
throw err;
|
|
193
|
+
};
|
|
194
|
+
let isResponseLogged = false;
|
|
195
|
+
try {
|
|
196
|
+
const { data, status, headers } = await this.request(reqOpts);
|
|
197
|
+
// `data` might be really big
|
|
198
|
+
// Be careful while handling it to avoid memory leaks
|
|
199
|
+
if (!lodash_1.default.isPlainObject(data)) {
|
|
200
|
+
// The response should be a valid JSON object
|
|
201
|
+
// If it cannot be coerced to an object then the response is wrong
|
|
202
|
+
throwProxyError(data);
|
|
203
|
+
}
|
|
204
|
+
this.log.debug(`Got response with status ${status}: ${truncateBody(data)}`);
|
|
205
|
+
isResponseLogged = true;
|
|
206
|
+
const isSessionCreationRequest = /\/session$/.test(url) && method === 'POST';
|
|
207
|
+
if (isSessionCreationRequest) {
|
|
208
|
+
if (status === 200) {
|
|
209
|
+
this.sessionId = data.sessionId || (data.value || {}).sessionId;
|
|
210
|
+
}
|
|
211
|
+
this.downstreamProtocol = this.getProtocolFromResBody(data);
|
|
212
|
+
this.log.info(`Determined the downstream protocol as '${this.downstreamProtocol}'`);
|
|
213
|
+
}
|
|
214
|
+
if (lodash_1.default.has(data, 'status') && parseInt(data.status, 10) !== 0) {
|
|
215
|
+
// Some servers, like chromedriver may return response code 200 for non-zero JSONWP statuses
|
|
216
|
+
throwProxyError(data);
|
|
217
|
+
}
|
|
218
|
+
const res = { statusCode: status, headers, body: data };
|
|
219
|
+
return [res, data];
|
|
220
|
+
}
|
|
221
|
+
catch (e) {
|
|
222
|
+
// We only consider an error unexpected if this was not
|
|
223
|
+
// an async request module error or if the response cannot be cast to
|
|
224
|
+
// a valid JSON
|
|
225
|
+
let proxyErrorMsg = e.message;
|
|
226
|
+
if (support_1.util.hasValue(e.response)) {
|
|
227
|
+
if (!isResponseLogged) {
|
|
228
|
+
const error = truncateBody(e.response.data);
|
|
229
|
+
this.log.info(support_1.util.hasValue(e.response.status)
|
|
230
|
+
? `Got response with status ${e.response.status}: ${error}`
|
|
231
|
+
: `Got response with unknown status: ${error}`);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
else {
|
|
235
|
+
proxyErrorMsg = `Could not proxy command to the remote server. Original error: ${e.message}`;
|
|
236
|
+
if (COMPACT_ERROR_PATTERNS.some((p) => p.test(e.message))) {
|
|
237
|
+
this.log.info(e.message);
|
|
238
|
+
}
|
|
239
|
+
else {
|
|
240
|
+
this.log.info(e.stack);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
throw new errors_1.errors.ProxyRequestError(proxyErrorMsg, e.response?.data, e.response?.status);
|
|
244
|
+
}
|
|
306
245
|
}
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
if (!commandName) {
|
|
315
|
-
return await this.proxy(url, method, body);
|
|
246
|
+
getProtocolFromResBody(resObj) {
|
|
247
|
+
if (lodash_1.default.isInteger(resObj.status)) {
|
|
248
|
+
return MJSONWP;
|
|
249
|
+
}
|
|
250
|
+
if (!lodash_1.default.isUndefined(resObj.value)) {
|
|
251
|
+
return W3C;
|
|
252
|
+
}
|
|
316
253
|
}
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
254
|
+
/**
|
|
255
|
+
*
|
|
256
|
+
* @param {string} url
|
|
257
|
+
* @param {import('@appium/types').HTTPMethod} method
|
|
258
|
+
* @returns {string|undefined}
|
|
259
|
+
*/
|
|
260
|
+
requestToCommandName(url, method) {
|
|
261
|
+
/**
|
|
262
|
+
*
|
|
263
|
+
* @param {RegExp} pattern
|
|
264
|
+
* @returns {string|undefined}
|
|
265
|
+
*/
|
|
266
|
+
const extractCommandName = (pattern) => {
|
|
267
|
+
const pathMatch = pattern.exec(url);
|
|
268
|
+
if (pathMatch) {
|
|
269
|
+
return (0, protocol_1.routeToCommandName)(pathMatch[1], method, this.reqBasePath);
|
|
270
|
+
}
|
|
271
|
+
};
|
|
272
|
+
let commandName = (0, protocol_1.routeToCommandName)(url, method, this.reqBasePath);
|
|
273
|
+
if (!commandName && lodash_1.default.includes(url, `${this.reqBasePath}/session/`)) {
|
|
274
|
+
commandName = extractCommandName(new RegExp(`${lodash_1.default.escapeRegExp(this.reqBasePath)}/session/[^/]+(.+)`));
|
|
275
|
+
}
|
|
276
|
+
if (!commandName && lodash_1.default.includes(url, this.reqBasePath)) {
|
|
277
|
+
commandName = extractCommandName(new RegExp(`${lodash_1.default.escapeRegExp(this.reqBasePath)}(/.+)`));
|
|
278
|
+
}
|
|
279
|
+
return commandName;
|
|
334
280
|
}
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
if (response.statusCode === 200 && resBodyObj.status === 0) {
|
|
340
|
-
return resBodyObj.value;
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
const status = parseInt(resBodyObj.status, 10);
|
|
344
|
-
|
|
345
|
-
if (!isNaN(status) && status !== 0) {
|
|
346
|
-
let message = resBodyObj.value;
|
|
347
|
-
|
|
348
|
-
if (_lodash.default.has(message, 'message')) {
|
|
349
|
-
message = message.message;
|
|
281
|
+
async proxyCommand(url, method, body = null) {
|
|
282
|
+
const commandName = this.requestToCommandName(url, method);
|
|
283
|
+
if (!commandName) {
|
|
284
|
+
return await this.proxy(url, method, body);
|
|
350
285
|
}
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
}
|
|
354
|
-
} else if (protocol === W3C) {
|
|
355
|
-
if (response.statusCode < 300) {
|
|
356
|
-
return resBodyObj.value;
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
if (_lodash.default.isPlainObject(resBodyObj.value) && resBodyObj.value.error) {
|
|
360
|
-
throw (0, _errors.errorFromW3CJsonCode)(resBodyObj.value.error, resBodyObj.value.message, resBodyObj.value.stacktrace);
|
|
361
|
-
}
|
|
362
|
-
} else if (response.statusCode === 200) {
|
|
363
|
-
return resBodyObj;
|
|
286
|
+
this.log.debug(`Matched '${url}' to command name '${commandName}'`);
|
|
287
|
+
return await this.protocolConverter.convertAndProxy(commandName, url, method, body);
|
|
364
288
|
}
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
289
|
+
async command(url, method, body = null) {
|
|
290
|
+
let response;
|
|
291
|
+
let resBodyObj;
|
|
292
|
+
try {
|
|
293
|
+
[response, resBodyObj] = await this.proxyCommand(url, method, body);
|
|
294
|
+
}
|
|
295
|
+
catch (err) {
|
|
296
|
+
if ((0, errors_1.isErrorType)(err, errors_1.errors.ProxyRequestError)) {
|
|
297
|
+
throw err.getActualError();
|
|
298
|
+
}
|
|
299
|
+
throw new errors_1.errors.UnknownError(err.message);
|
|
300
|
+
}
|
|
301
|
+
const protocol = this.getProtocolFromResBody(resBodyObj);
|
|
302
|
+
if (protocol === MJSONWP) {
|
|
303
|
+
// Got response in MJSONWP format
|
|
304
|
+
if (response.statusCode === 200 && resBodyObj.status === 0) {
|
|
305
|
+
return resBodyObj.value;
|
|
306
|
+
}
|
|
307
|
+
const status = parseInt(resBodyObj.status, 10);
|
|
308
|
+
if (!isNaN(status) && status !== 0) {
|
|
309
|
+
let message = resBodyObj.value;
|
|
310
|
+
if (lodash_1.default.has(message, 'message')) {
|
|
311
|
+
message = message.message;
|
|
312
|
+
}
|
|
313
|
+
throw (0, errors_1.errorFromMJSONWPStatusCode)(status, lodash_1.default.isEmpty(message) ? (0, status_1.getSummaryByCode)(status) : message);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
else if (protocol === W3C) {
|
|
317
|
+
// Got response in W3C format
|
|
318
|
+
if (response.statusCode < 300) {
|
|
319
|
+
return resBodyObj.value;
|
|
320
|
+
}
|
|
321
|
+
if (lodash_1.default.isPlainObject(resBodyObj.value) && resBodyObj.value.error) {
|
|
322
|
+
throw (0, errors_1.errorFromW3CJsonCode)(resBodyObj.value.error, resBodyObj.value.message, resBodyObj.value.stacktrace);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
else if (response.statusCode === 200) {
|
|
326
|
+
// Unknown protocol. Keeping it because of the backward compatibility
|
|
327
|
+
return resBodyObj;
|
|
328
|
+
}
|
|
329
|
+
throw new errors_1.errors.UnknownError(`Did not know what to do with response code '${response.statusCode}' ` +
|
|
330
|
+
`and response body '${lodash_1.default.truncate(JSON.stringify(resBodyObj), {
|
|
331
|
+
length: 300,
|
|
332
|
+
})}'`);
|
|
387
333
|
}
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
if (!_lodash.default.isPlainObject(resBodyObj)) {
|
|
392
|
-
const error = new _errors.errors.UnknownError(`The downstream server response with the status code ${statusCode} is not a valid JSON object: ` + _lodash.default.truncate(`${resBodyObj}`, {
|
|
393
|
-
length: 300
|
|
394
|
-
}));
|
|
395
|
-
[statusCode, resBodyObj] = (0, _errors.getResponseForW3CError)(error);
|
|
334
|
+
getSessionIdFromUrl(url) {
|
|
335
|
+
const match = url.match(/\/session\/([^/]+)/);
|
|
336
|
+
return match ? match[1] : null;
|
|
396
337
|
}
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
338
|
+
async proxyReqRes(req, res) {
|
|
339
|
+
// ! this method must not throw any exceptions
|
|
340
|
+
// ! make sure to call res.send before return
|
|
341
|
+
let statusCode;
|
|
342
|
+
let resBodyObj;
|
|
343
|
+
try {
|
|
344
|
+
let response;
|
|
345
|
+
[response, resBodyObj] = await this.proxyCommand(req.originalUrl, req.method, req.body);
|
|
346
|
+
res.headers = response.headers;
|
|
347
|
+
statusCode = response.statusCode;
|
|
348
|
+
}
|
|
349
|
+
catch (err) {
|
|
350
|
+
[statusCode, resBodyObj] = (0, errors_1.getResponseForW3CError)((0, errors_1.isErrorType)(err, errors_1.errors.ProxyRequestError) ? err.getActualError() : err);
|
|
351
|
+
}
|
|
352
|
+
res.set('content-type', 'application/json; charset=utf-8');
|
|
353
|
+
if (!lodash_1.default.isPlainObject(resBodyObj)) {
|
|
354
|
+
const error = new errors_1.errors.UnknownError(`The downstream server response with the status code ${statusCode} is not a valid JSON object: ` +
|
|
355
|
+
lodash_1.default.truncate(`${resBodyObj}`, { length: 300 }));
|
|
356
|
+
[statusCode, resBodyObj] = (0, errors_1.getResponseForW3CError)(error);
|
|
357
|
+
}
|
|
358
|
+
// if the proxied response contains a sessionId that the downstream
|
|
359
|
+
// driver has generated, we don't want to return that to the client.
|
|
360
|
+
// Instead, return the id from the request or from current session
|
|
361
|
+
if (lodash_1.default.has(resBodyObj, 'sessionId')) {
|
|
362
|
+
const reqSessionId = this.getSessionIdFromUrl(req.originalUrl);
|
|
363
|
+
if (reqSessionId) {
|
|
364
|
+
this.log.info(`Replacing sessionId ${resBodyObj.sessionId} with ${reqSessionId}`);
|
|
365
|
+
resBodyObj.sessionId = reqSessionId;
|
|
366
|
+
}
|
|
367
|
+
else if (this.sessionId) {
|
|
368
|
+
this.log.info(`Replacing sessionId ${resBodyObj.sessionId} with ${this.sessionId}`);
|
|
369
|
+
resBodyObj.sessionId = this.sessionId;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
resBodyObj.value = (0, helpers_1.formatResponseValue)(resBodyObj.value);
|
|
373
|
+
res.status(statusCode).send(JSON.stringify((0, helpers_1.formatStatus)(resBodyObj)));
|
|
408
374
|
}
|
|
409
|
-
|
|
410
|
-
resBodyObj.value = (0, _helpers.formatResponseValue)(resBodyObj.value);
|
|
411
|
-
res.status(statusCode).send(JSON.stringify((0, _helpers.formatStatus)(resBodyObj)));
|
|
412
|
-
}
|
|
413
|
-
|
|
414
375
|
}
|
|
415
|
-
|
|
416
376
|
exports.JWProxy = JWProxy;
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJERUZBVUxUX0xPRyIsImxvZ2dlciIsImdldExvZ2dlciIsIkRFRkFVTFRfUkVRVUVTVF9USU1FT1VUIiwiQ09NUEFDVF9FUlJPUl9QQVRURVJOUyIsIk1KU09OV1AiLCJXM0MiLCJQUk9UT0NPTFMiLCJBTExPV0VEX09QVFMiLCJKV1Byb3h5Iiwic2NoZW1lIiwic2VydmVyIiwicG9ydCIsImJhc2UiLCJyZXFCYXNlUGF0aCIsInNlc3Npb25JZCIsInRpbWVvdXQiLCJjb25zdHJ1Y3RvciIsIm9wdHMiLCJfIiwicGljayIsIm9wdGlvbnMiLCJkZWZhdWx0cyIsIm9taXQiLCJERUZBVUxUX0JBU0VfUEFUSCIsInRvTG93ZXJDYXNlIiwiT2JqZWN0IiwiYXNzaWduIiwiX2FjdGl2ZVJlcXVlc3RzIiwiX2Rvd25zdHJlYW1Qcm90b2NvbCIsImFnZW50T3B0cyIsImtlZXBBbGl2ZSIsIm1heFNvY2tldHMiLCJtYXhGcmVlU29ja2V0cyIsImh0dHBBZ2VudCIsImh0dHAiLCJBZ2VudCIsImh0dHBzQWdlbnQiLCJodHRwcyIsInByb3RvY29sQ29udmVydGVyIiwiUHJvdG9jb2xDb252ZXJ0ZXIiLCJwcm94eSIsImJpbmQiLCJsb2ciLCJfbG9nIiwicmVxdWVzdCIsInJlcXVlc3RDb25maWciLCJyZXFQcm9taXNlIiwiYXhpb3MiLCJwdXNoIiwicHVsbCIsImdldEFjdGl2ZVJlcXVlc3RzQ291bnQiLCJsZW5ndGgiLCJjYW5jZWxBY3RpdmVSZXF1ZXN0cyIsImVuZHBvaW50UmVxdWlyZXNTZXNzaW9uSWQiLCJlbmRwb2ludCIsImluY2x1ZGVzIiwiZG93bnN0cmVhbVByb3RvY29sIiwidmFsdWUiLCJnZXRVcmxGb3JQcm94eSIsInVybCIsInByb3h5QmFzZSIsImVuZHBvaW50UmUiLCJyZW1haW5pbmdVcmwiLCJ0ZXN0IiwiZmlyc3QiLCJSZWdFeHAiLCJleGVjIiwiRXJyb3IiLCJyZXBsYWNlIiwic3RyaXBQcmVmaXhSZSIsInJlcXVpcmVzU2Vzc2lvbklkIiwic2Vzc2lvbkJhc2VSZSIsIlJlZmVyZW5jZUVycm9yIiwibWF0Y2giLCJtZXRob2QiLCJib2R5IiwidG9VcHBlckNhc2UiLCJuZXdVcmwiLCJ0cnVuY2F0ZUJvZHkiLCJjb250ZW50IiwidHJ1bmNhdGUiLCJpc1N0cmluZyIsIkpTT04iLCJzdHJpbmdpZnkiLCJNQVhfTE9HX0JPRFlfTEVOR1RIIiwicmVxT3B0cyIsImhlYWRlcnMiLCJhY2NlcHQiLCJ1dGlsIiwiaGFzVmFsdWUiLCJkYXRhIiwicGFyc2UiLCJlIiwiZGVidWciLCJ0aHJvd1Byb3h5RXJyb3IiLCJlcnJvciIsImVyciIsInJlc3BvbnNlIiwic3RhdHVzIiwiaXNSZXNwb25zZUxvZ2dlZCIsImlzUGxhaW5PYmplY3QiLCJpc1Nlc3Npb25DcmVhdGlvblJlcXVlc3QiLCJnZXRQcm90b2NvbEZyb21SZXNCb2R5IiwiaW5mbyIsImhhcyIsInBhcnNlSW50IiwicmVzIiwic3RhdHVzQ29kZSIsInByb3h5RXJyb3JNc2ciLCJtZXNzYWdlIiwic29tZSIsInAiLCJzdGFjayIsImVycm9ycyIsIlByb3h5UmVxdWVzdEVycm9yIiwicmVzT2JqIiwiaXNJbnRlZ2VyIiwiaXNVbmRlZmluZWQiLCJyZXF1ZXN0VG9Db21tYW5kTmFtZSIsImV4dHJhY3RDb21tYW5kTmFtZSIsInBhdHRlcm4iLCJwYXRoTWF0Y2giLCJyb3V0ZVRvQ29tbWFuZE5hbWUiLCJjb21tYW5kTmFtZSIsImVzY2FwZVJlZ0V4cCIsInByb3h5Q29tbWFuZCIsImNvbnZlcnRBbmRQcm94eSIsImNvbW1hbmQiLCJyZXNCb2R5T2JqIiwiaXNFcnJvclR5cGUiLCJnZXRBY3R1YWxFcnJvciIsIlVua25vd25FcnJvciIsInByb3RvY29sIiwiaXNOYU4iLCJlcnJvckZyb21NSlNPTldQU3RhdHVzQ29kZSIsImlzRW1wdHkiLCJnZXRTdW1tYXJ5QnlDb2RlIiwiZXJyb3JGcm9tVzNDSnNvbkNvZGUiLCJzdGFja3RyYWNlIiwiZ2V0U2Vzc2lvbklkRnJvbVVybCIsInByb3h5UmVxUmVzIiwicmVxIiwib3JpZ2luYWxVcmwiLCJnZXRSZXNwb25zZUZvclczQ0Vycm9yIiwic2V0IiwicmVxU2Vzc2lvbklkIiwiZm9ybWF0UmVzcG9uc2VWYWx1ZSIsInNlbmQiLCJmb3JtYXRTdGF0dXMiXSwic291cmNlcyI6WyIuLi8uLi8uLi9saWIvanNvbndwLXByb3h5L3Byb3h5LmpzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBfIGZyb20gJ2xvZGFzaCc7XG5pbXBvcnQge2xvZ2dlciwgdXRpbH0gZnJvbSAnQGFwcGl1bS9zdXBwb3J0JztcbmltcG9ydCBheGlvcyBmcm9tICdheGlvcyc7XG5pbXBvcnQge2dldFN1bW1hcnlCeUNvZGV9IGZyb20gJy4uL2pzb253cC1zdGF0dXMvc3RhdHVzJztcbmltcG9ydCB7XG4gIGVycm9ycyxcbiAgaXNFcnJvclR5cGUsXG4gIGVycm9yRnJvbU1KU09OV1BTdGF0dXNDb2RlLFxuICBlcnJvckZyb21XM0NKc29uQ29kZSxcbiAgZ2V0UmVzcG9uc2VGb3JXM0NFcnJvcixcbn0gZnJvbSAnLi4vcHJvdG9jb2wvZXJyb3JzJztcbmltcG9ydCB7cm91dGVUb0NvbW1hbmROYW1lfSBmcm9tICcuLi9wcm90b2NvbCc7XG5pbXBvcnQge01BWF9MT0dfQk9EWV9MRU5HVEgsIERFRkFVTFRfQkFTRV9QQVRILCBQUk9UT0NPTFN9IGZyb20gJy4uL2NvbnN0YW50cyc7XG5pbXBvcnQgUHJvdG9jb2xDb252ZXJ0ZXIgZnJvbSAnLi9wcm90b2NvbC1jb252ZXJ0ZXInO1xuaW1wb3J0IHtmb3JtYXRSZXNwb25zZVZhbHVlLCBmb3JtYXRTdGF0dXN9IGZyb20gJy4uL3Byb3RvY29sL2hlbHBlcnMnO1xuaW1wb3J0IGh0dHAgZnJvbSAnaHR0cCc7XG5pbXBvcnQgaHR0cHMgZnJvbSAnaHR0cHMnO1xuXG5jb25zdCBERUZBVUxUX0xPRyA9IGxvZ2dlci5nZXRMb2dnZXIoJ1dEIFByb3h5Jyk7XG5jb25zdCBERUZBVUxUX1JFUVVFU1RfVElNRU9VVCA9IDI0MDAwMDtcbmNvbnN0IENPTVBBQ1RfRVJST1JfUEFUVEVSTlMgPSBbL1xcYkVDT05OUkVGVVNFRFxcYi8sIC9zb2NrZXQgaGFuZyB1cC9dO1xuXG5jb25zdCB7TUpTT05XUCwgVzNDfSA9IFBST1RPQ09MUztcblxuY29uc3QgQUxMT1dFRF9PUFRTID0gW1xuICAnc2NoZW1lJyxcbiAgJ3NlcnZlcicsXG4gICdwb3J0JyxcbiAgJ2Jhc2UnLFxuICAncmVxQmFzZVBhdGgnLFxuICAnc2Vzc2lvbklkJyxcbiAgJ3RpbWVvdXQnLFxuICAnbG9nJyxcbiAgJ2tlZXBBbGl2ZScsXG5dO1xuXG5jbGFzcyBKV1Byb3h5IHtcbiAgLyoqIEB0eXBlIHtzdHJpbmd9ICovXG4gIHNjaGVtZTtcbiAgLyoqIEB0eXBlIHtzdHJpbmd9ICovXG4gIHNlcnZlcjtcbiAgLyoqIEB0eXBlIHtudW1iZXJ9ICovXG4gIHBvcnQ7XG4gIC8qKiBAdHlwZSB7c3RyaW5nfSAqL1xuICBiYXNlO1xuICAvKiogQHR5cGUge3N0cmluZ30gKi9cbiAgcmVxQmFzZVBhdGg7XG4gIC8qKiBAdHlwZSB7c3RyaW5nP30gKi9cbiAgc2Vzc2lvbklkO1xuICAvKiogQHR5cGUge251bWJlcn0gKi9cbiAgdGltZW91dDtcblxuICBjb25zdHJ1Y3RvcihvcHRzID0ge30pIHtcbiAgICBvcHRzID0gXy5waWNrKG9wdHMsIEFMTE9XRURfT1BUUyk7XG5cbiAgICAvLyBvbWl0ICdsb2cnIGluIHRoZSBkZWZhdWx0cyBhc3NpZ25tZW50IGhlcmUgYmVjYXVzZSAnbG9nJyBpcyBhIGdldHRlciBhbmQgd2UgYXJlIGdvaW5nIHRvIHNldFxuICAgIC8vIGl0IHRvIHRoaXMuX2xvZyAod2hpY2ggbGllcyBiZWhpbmQgdGhlIGdldHRlcikgZnVydGhlciBkb3duXG4gICAgY29uc3Qgb3B0aW9ucyA9IF8uZGVmYXVsdHMoXy5vbWl0KG9wdHMsICdsb2cnKSwge1xuICAgICAgc2NoZW1lOiAnaHR0cCcsXG4gICAgICBzZXJ2ZXI6ICdsb2NhbGhvc3QnLFxuICAgICAgcG9ydDogNDQ0NCxcbiAgICAgIGJhc2U6IERFRkFVTFRfQkFTRV9QQVRILFxuICAgICAgcmVxQmFzZVBhdGg6IERFRkFVTFRfQkFTRV9QQVRILFxuICAgICAgc2Vzc2lvbklkOiBudWxsLFxuICAgICAgdGltZW91dDogREVGQVVMVF9SRVFVRVNUX1RJTUVPVVQsXG4gICAgfSk7XG4gICAgb3B0aW9ucy5zY2hlbWUgPSBvcHRpb25zLnNjaGVtZS50b0xvd2VyQ2FzZSgpO1xuICAgIE9iamVjdC5hc3NpZ24odGhpcywgb3B0aW9ucyk7XG5cbiAgICB0aGlzLl9hY3RpdmVSZXF1ZXN0cyA9IFtdO1xuICAgIHRoaXMuX2Rvd25zdHJlYW1Qcm90b2NvbCA9IG51bGw7XG4gICAgY29uc3QgYWdlbnRPcHRzID0ge1xuICAgICAga2VlcEFsaXZlOiBvcHRzLmtlZXBBbGl2ZSA/PyB0cnVlLFxuICAgICAgbWF4U29ja2V0czogMTAsXG4gICAgICBtYXhGcmVlU29ja2V0czogNSxcbiAgICB9O1xuICAgIHRoaXMuaHR0cEFnZW50ID0gbmV3IGh0dHAuQWdlbnQoYWdlbnRPcHRzKTtcbiAgICB0aGlzLmh0dHBzQWdlbnQgPSBuZXcgaHR0cHMuQWdlbnQoYWdlbnRPcHRzKTtcbiAgICB0aGlzLnByb3RvY29sQ29udmVydGVyID0gbmV3IFByb3RvY29sQ29udmVydGVyKHRoaXMucHJveHkuYmluZCh0aGlzKSwgb3B0cy5sb2cpO1xuICAgIHRoaXMuX2xvZyA9IG9wdHMubG9nO1xuICB9XG5cbiAgZ2V0IGxvZygpIHtcbiAgICByZXR1cm4gdGhpcy5fbG9nID8/IERFRkFVTFRfTE9HO1xuICB9XG5cbiAgLyoqXG4gICAqIFBlcmZvcm1zIHJlcXVlc3RzIHRvIHRoZSBkb3duc3RyZWFtIHNlcnZlclxuICAgKlxuICAgKiBAcHJpdmF0ZSAtIERvIG5vdCBjYWxsIHRoaXMgbWV0aG9kIGRpcmVjdGx5LFxuICAgKiBpdCB1c2VzIGNsaWVudC1zcGVjaWZpYyBhcmd1bWVudHMgYW5kIHJlc3BvbnNlcyFcbiAgICpcbiAgICogQHBhcmFtIHtpbXBvcnQoJ2F4aW9zJykuQXhpb3NSZXF1ZXN0Q29uZmlnfSByZXF1ZXN0Q29uZmlnXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPGltcG9ydCgnYXhpb3MnKS5BeGlvc1Jlc3BvbnNlPn1cbiAgICovXG4gIGFzeW5jIHJlcXVlc3QocmVxdWVzdENvbmZpZykge1xuICAgIGNvbnN0IHJlcVByb21pc2UgPSBheGlvcyhyZXF1ZXN0Q29uZmlnKTtcbiAgICB0aGlzLl9hY3RpdmVSZXF1ZXN0cy5wdXNoKHJlcVByb21pc2UpO1xuICAgIHRyeSB7XG4gICAgICByZXR1cm4gYXdhaXQgcmVxUHJvbWlzZTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgXy5wdWxsKHRoaXMuX2FjdGl2ZVJlcXVlc3RzLCByZXFQcm9taXNlKTtcbiAgICB9XG4gIH1cblxuICBnZXRBY3RpdmVSZXF1ZXN0c0NvdW50KCkge1xuICAgIHJldHVybiB0aGlzLl9hY3RpdmVSZXF1ZXN0cy5sZW5ndGg7XG4gIH1cblxuICBjYW5jZWxBY3RpdmVSZXF1ZXN0cygpIHtcbiAgICB0aGlzLl9hY3RpdmVSZXF1ZXN0cyA9IFtdO1xuICB9XG5cbiAgZW5kcG9pbnRSZXF1aXJlc1Nlc3Npb25JZChlbmRwb2ludCkge1xuICAgIHJldHVybiAhXy5pbmNsdWRlcyhbJy9zZXNzaW9uJywgJy9zZXNzaW9ucycsICcvc3RhdHVzJ10sIGVuZHBvaW50KTtcbiAgfVxuXG4gIHNldCBkb3duc3RyZWFtUHJvdG9jb2wodmFsdWUpIHtcbiAgICB0aGlzLl9kb3duc3RyZWFtUHJvdG9jb2wgPSB2YWx1ZTtcbiAgICB0aGlzLnByb3RvY29sQ29udmVydGVyLmRvd25zdHJlYW1Qcm90b2NvbCA9IHZhbHVlO1xuICB9XG5cbiAgZ2V0IGRvd25zdHJlYW1Qcm90b2NvbCgpIHtcbiAgICByZXR1cm4gdGhpcy5fZG93bnN0cmVhbVByb3RvY29sO1xuICB9XG5cbiAgZ2V0VXJsRm9yUHJveHkodXJsKSB7XG4gICAgaWYgKHVybCA9PT0gJycpIHtcbiAgICAgIHVybCA9ICcvJztcbiAgICB9XG4gICAgY29uc3QgcHJveHlCYXNlID0gYCR7dGhpcy5zY2hlbWV9Oi8vJHt0aGlzLnNlcnZlcn06JHt0aGlzLnBvcnR9JHt0aGlzLmJhc2V9YDtcbiAgICBjb25zdCBlbmRwb2ludFJlID0gJygvKHNlc3Npb258c3RhdHVzKSknO1xuICAgIGxldCByZW1haW5pbmdVcmwgPSAnJztcbiAgICBpZiAoL15odHRwLy50ZXN0KHVybCkpIHtcbiAgICAgIGNvbnN0IGZpcnN0ID0gbmV3IFJlZ0V4cChgKGh0dHBzPzovLy4rKSR7ZW5kcG9pbnRSZX1gKS5leGVjKHVybCk7XG4gICAgICBpZiAoIWZpcnN0KSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignR290IGEgY29tcGxldGUgdXJsIGJ1dCBjb3VsZCBub3QgZXh0cmFjdCBKV1AgZW5kcG9pbnQnKTtcbiAgICAgIH1cbiAgICAgIHJlbWFpbmluZ1VybCA9IHVybC5yZXBsYWNlKGZpcnN0WzFdLCAnJyk7XG4gICAgfSBlbHNlIGlmIChuZXcgUmVnRXhwKCdeLycpLnRlc3QodXJsKSkge1xuICAgICAgcmVtYWluaW5nVXJsID0gdXJsO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYERpZCBub3Qga25vdyB3aGF0IHRvIGRvIHdpdGggdXJsICcke3VybH0nYCk7XG4gICAgfVxuXG4gICAgY29uc3Qgc3RyaXBQcmVmaXhSZSA9IG5ldyBSZWdFeHAoJ14uKj8oLyhzZXNzaW9ufHN0YXR1cykuKikkJyk7XG4gICAgaWYgKHN0cmlwUHJlZml4UmUudGVzdChyZW1haW5pbmdVcmwpKSB7XG4gICAgICByZW1haW5pbmdVcmwgPSAvKiogQHR5cGUge1JlZ0V4cEV4ZWNBcnJheX0gKi8gKHN0cmlwUHJlZml4UmUuZXhlYyhyZW1haW5pbmdVcmwpKVsxXTtcbiAgICB9XG5cbiAgICBpZiAoIW5ldyBSZWdFeHAoZW5kcG9pbnRSZSkudGVzdChyZW1haW5pbmdVcmwpKSB7XG4gICAgICByZW1haW5pbmdVcmwgPSBgL3Nlc3Npb24vJHt0aGlzLnNlc3Npb25JZH0ke3JlbWFpbmluZ1VybH1gO1xuICAgIH1cblxuICAgIGNvbnN0IHJlcXVpcmVzU2Vzc2lvbklkID0gdGhpcy5lbmRwb2ludFJlcXVpcmVzU2Vzc2lvbklkKHJlbWFpbmluZ1VybCk7XG5cbiAgICBpZiAocmVxdWlyZXNTZXNzaW9uSWQgJiYgdGhpcy5zZXNzaW9uSWQgPT09IG51bGwpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignVHJ5aW5nIHRvIHByb3h5IGEgc2Vzc2lvbiBjb21tYW5kIHdpdGhvdXQgc2Vzc2lvbiBpZCcpO1xuICAgIH1cblxuICAgIGNvbnN0IHNlc3Npb25CYXNlUmUgPSBuZXcgUmVnRXhwKCdeL3Nlc3Npb24vKFteL10rKScpO1xuICAgIGlmIChzZXNzaW9uQmFzZVJlLnRlc3QocmVtYWluaW5nVXJsKSkge1xuICAgICAgaWYgKHRoaXMuc2Vzc2lvbklkID09PSBudWxsKSB7XG4gICAgICAgIHRocm93IG5ldyBSZWZlcmVuY2VFcnJvcihcbiAgICAgICAgICBgU2Vzc2lvbiBJRCBpcyBub3Qgc2V0LCBidXQgc2F3IGEgVVJMIHBhdGggcmVmZXJlbmNpbmcgYSBzZXNzaW9uICgke3JlbWFpbmluZ1VybH0pLiBUaGlzIG1heSBiZSBhIGJ1ZyBpbiB5b3VyIGNsaWVudC5gXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICAvLyB3ZSBoYXZlIHNvbWV0aGluZyBsaWtlIC9zZXNzaW9uLzppZC9mb29iYXIsIHNvIHdlIG5lZWQgdG8gcmVwbGFjZVxuICAgICAgLy8gdGhlIHNlc3Npb24gaWRcbiAgICAgIGNvbnN0IG1hdGNoID0gc2Vzc2lvbkJhc2VSZS5leGVjKHJlbWFpbmluZ1VybCk7XG4gICAgICAvLyBUT0RPOiBpZiBgcmVxdWlyZXNTZXNzaW9uSWRgIGlzIGBmYWxzZWAgYW5kIGBzZXNzaW9uSWRgIGlzIGBudWxsYCwgdGhpcyBpcyBhIGJ1Zy5cbiAgICAgIC8vIGFyZSB3ZSBzdXJlIGBzZXNzaW9uSWRgIGlzIG5vdCBgbnVsbGA/XG4gICAgICByZW1haW5pbmdVcmwgPSByZW1haW5pbmdVcmwucmVwbGFjZShcbiAgICAgICAgLyoqIEB0eXBlIHtSZWdFeHBFeGVjQXJyYXl9ICovIChtYXRjaClbMV0sXG4gICAgICAgIC8qKiBAdHlwZSB7c3RyaW5nfSAqLyAodGhpcy5zZXNzaW9uSWQpXG4gICAgICApO1xuICAgIH0gZWxzZSBpZiAocmVxdWlyZXNTZXNzaW9uSWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgQ291bGQgbm90IGZpbmQgOnNlc3Npb24gc2VjdGlvbiBmb3IgdXJsOiAke3JlbWFpbmluZ1VybH1gKTtcbiAgICB9XG4gICAgcmVtYWluaW5nVXJsID0gcmVtYWluaW5nVXJsLnJlcGxhY2UoL1xcLyQvLCAnJyk7IC8vIGNhbid0IGhhdmUgdHJhaWxpbmcgc2xhc2hlc1xuXG4gICAgcmV0dXJuIHByb3h5QmFzZSArIHJlbWFpbmluZ1VybDtcbiAgfVxuXG4gIGFzeW5jIHByb3h5KHVybCwgbWV0aG9kLCBib2R5ID0gbnVsbCkge1xuICAgIG1ldGhvZCA9IG1ldGhvZC50b1VwcGVyQ2FzZSgpO1xuICAgIGNvbnN0IG5ld1VybCA9IHRoaXMuZ2V0VXJsRm9yUHJveHkodXJsKTtcbiAgICBjb25zdCB0cnVuY2F0ZUJvZHkgPSAoY29udGVudCkgPT5cbiAgICAgIF8udHJ1bmNhdGUoXy5pc1N0cmluZyhjb250ZW50KSA/IGNvbnRlbnQgOiBKU09OLnN0cmluZ2lmeShjb250ZW50KSwge1xuICAgICAgICBsZW5ndGg6IE1BWF9MT0dfQk9EWV9MRU5HVEgsXG4gICAgICB9KTtcbiAgICAvKiogQHR5cGUge2ltcG9ydCgnYXhpb3MnKS5BeGlvc1JlcXVlc3RDb25maWd9ICovXG4gICAgY29uc3QgcmVxT3B0cyA9IHtcbiAgICAgIHVybDogbmV3VXJsLFxuICAgICAgbWV0aG9kLFxuICAgICAgaGVhZGVyczoge1xuICAgICAgICAnY29udGVudC10eXBlJzogJ2FwcGxpY2F0aW9uL2pzb247IGNoYXJzZXQ9dXRmLTgnLFxuICAgICAgICAndXNlci1hZ2VudCc6ICdhcHBpdW0nLFxuICAgICAgICBhY2NlcHQ6ICdhcHBsaWNhdGlvbi9qc29uLCAqLyonLFxuICAgICAgfSxcbiAgICAgIHByb3h5OiBmYWxzZSxcbiAgICAgIHRpbWVvdXQ6IHRoaXMudGltZW91dCxcbiAgICAgIGh0dHBBZ2VudDogdGhpcy5odHRwQWdlbnQsXG4gICAgICBodHRwc0FnZW50OiB0aGlzLmh0dHBzQWdlbnQsXG4gICAgfTtcbiAgICAvLyBHRVQgbWV0aG9kcyBzaG91bGRuJ3QgaGF2ZSBhbnkgYm9keS4gTW9zdCBzZXJ2ZXJzIGFyZSBPSyB3aXRoIHRoaXMsIGJ1dCBXZWJEcml2ZXJBZ2VudCB0aHJvd3MgNDAwIGVycm9yc1xuICAgIGlmICh1dGlsLmhhc1ZhbHVlKGJvZHkpICYmIG1ldGhvZCAhPT0gJ0dFVCcpIHtcbiAgICAgIGlmICh0eXBlb2YgYm9keSAhPT0gJ29iamVjdCcpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICByZXFPcHRzLmRhdGEgPSBKU09OLnBhcnNlKGJvZHkpO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBDYW5ub3QgaW50ZXJwcmV0IHRoZSByZXF1ZXN0IGJvZHkgYXMgdmFsaWQgSlNPTjogJHt0cnVuY2F0ZUJvZHkoYm9keSl9YCk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJlcU9wdHMuZGF0YSA9IGJvZHk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhpcy5sb2cuZGVidWcoXG4gICAgICBgUHJveHlpbmcgWyR7bWV0aG9kfSAke3VybCB8fCAnLyd9XSB0byBbJHttZXRob2R9ICR7bmV3VXJsfV0gYCArXG4gICAgICAgIChyZXFPcHRzLmRhdGEgPyBgd2l0aCBib2R5OiAke3RydW5jYXRlQm9keShyZXFPcHRzLmRhdGEpfWAgOiAnd2l0aCBubyBib2R5JylcbiAgICApO1xuXG4gICAgY29uc3QgdGhyb3dQcm94eUVycm9yID0gKGVycm9yKSA9PiB7XG4gICAgICBjb25zdCBlcnIgPSAvKiogQHR5cGUge1Byb3h5RXJyb3J9ICovIChuZXcgRXJyb3IoYFRoZSByZXF1ZXN0IHRvICR7dXJsfSBoYXMgZmFpbGVkYCkpO1xuICAgICAgZXJyLnJlc3BvbnNlID0ge1xuICAgICAgICBkYXRhOiBlcnJvcixcbiAgICAgICAgc3RhdHVzOiA1MDAsXG4gICAgICB9O1xuICAgICAgdGhyb3cgZXJyO1xuICAgIH07XG4gICAgbGV0IGlzUmVzcG9uc2VMb2dnZWQgPSBmYWxzZTtcbiAgICB0cnkge1xuICAgICAgY29uc3Qge2RhdGEsIHN0YXR1cywgaGVhZGVyc30gPSBhd2FpdCB0aGlzLnJlcXVlc3QocmVxT3B0cyk7XG4gICAgICAvLyBgZGF0YWAgbWlnaHQgYmUgcmVhbGx5IGJpZ1xuICAgICAgLy8gQmUgY2FyZWZ1bCB3aGlsZSBoYW5kbGluZyBpdCB0byBhdm9pZCBtZW1vcnkgbGVha3NcbiAgICAgIGlmICghXy5pc1BsYWluT2JqZWN0KGRhdGEpKSB7XG4gICAgICAgIC8vIFRoZSByZXNwb25zZSBzaG91bGQgYmUgYSB2YWxpZCBKU09OIG9iamVjdFxuICAgICAgICAvLyBJZiBpdCBjYW5ub3QgYmUgY29lcmNlZCB0byBhbiBvYmplY3QgdGhlbiB0aGUgcmVzcG9uc2UgaXMgd3JvbmdcbiAgICAgICAgdGhyb3dQcm94eUVycm9yKGRhdGEpO1xuICAgICAgfVxuICAgICAgdGhpcy5sb2cuZGVidWcoYEdvdCByZXNwb25zZSB3aXRoIHN0YXR1cyAke3N0YXR1c306ICR7dHJ1bmNhdGVCb2R5KGRhdGEpfWApO1xuICAgICAgaXNSZXNwb25zZUxvZ2dlZCA9IHRydWU7XG4gICAgICBjb25zdCBpc1Nlc3Npb25DcmVhdGlvblJlcXVlc3QgPSAvXFwvc2Vzc2lvbiQvLnRlc3QodXJsKSAmJiBtZXRob2QgPT09ICdQT1NUJztcbiAgICAgIGlmIChpc1Nlc3Npb25DcmVhdGlvblJlcXVlc3QpIHtcbiAgICAgICAgaWYgKHN0YXR1cyA9PT0gMjAwKSB7XG4gICAgICAgICAgdGhpcy5zZXNzaW9uSWQgPSBkYXRhLnNlc3Npb25JZCB8fCAoZGF0YS52YWx1ZSB8fCB7fSkuc2Vzc2lvbklkO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuZG93bnN0cmVhbVByb3RvY29sID0gdGhpcy5nZXRQcm90b2NvbEZyb21SZXNCb2R5KGRhdGEpO1xuICAgICAgICB0aGlzLmxvZy5pbmZvKGBEZXRlcm1pbmVkIHRoZSBkb3duc3RyZWFtIHByb3RvY29sIGFzICcke3RoaXMuZG93bnN0cmVhbVByb3RvY29sfSdgKTtcbiAgICAgIH1cbiAgICAgIGlmIChfLmhhcyhkYXRhLCAnc3RhdHVzJykgJiYgcGFyc2VJbnQoZGF0YS5zdGF0dXMsIDEwKSAhPT0gMCkge1xuICAgICAgICAvLyBTb21lIHNlcnZlcnMsIGxpa2UgY2hyb21lZHJpdmVyIG1heSByZXR1cm4gcmVzcG9uc2UgY29kZSAyMDAgZm9yIG5vbi16ZXJvIEpTT05XUCBzdGF0dXNlc1xuICAgICAgICB0aHJvd1Byb3h5RXJyb3IoZGF0YSk7XG4gICAgICB9XG4gICAgICBjb25zdCByZXMgPSB7c3RhdHVzQ29kZTogc3RhdHVzLCBoZWFkZXJzLCBib2R5OiBkYXRhfTtcbiAgICAgIHJldHVybiBbcmVzLCBkYXRhXTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAvLyBXZSBvbmx5IGNvbnNpZGVyIGFuIGVycm9yIHVuZXhwZWN0ZWQgaWYgdGhpcyB3YXMgbm90XG4gICAgICAvLyBhbiBhc3luYyByZXF1ZXN0IG1vZHVsZSBlcnJvciBvciBpZiB0aGUgcmVzcG9uc2UgY2Fubm90IGJlIGNhc3QgdG9cbiAgICAgIC8vIGEgdmFsaWQgSlNPTlxuICAgICAgbGV0IHByb3h5RXJyb3JNc2cgPSBlLm1lc3NhZ2U7XG4gICAgICBpZiAodXRpbC5oYXNWYWx1ZShlLnJlc3BvbnNlKSkge1xuICAgICAgICBpZiAoIWlzUmVzcG9uc2VMb2dnZWQpIHtcbiAgICAgICAgICBjb25zdCBlcnJvciA9IHRydW5jYXRlQm9keShlLnJlc3BvbnNlLmRhdGEpO1xuICAgICAgICAgIHRoaXMubG9nLmluZm8oXG4gICAgICAgICAgICB1dGlsLmhhc1ZhbHVlKGUucmVzcG9uc2Uuc3RhdHVzKVxuICAgICAgICAgICAgICA/IGBHb3QgcmVzcG9uc2Ugd2l0aCBzdGF0dXMgJHtlLnJlc3BvbnNlLnN0YXR1c306ICR7ZXJyb3J9YFxuICAgICAgICAgICAgICA6IGBHb3QgcmVzcG9uc2Ugd2l0aCB1bmtub3duIHN0YXR1czogJHtlcnJvcn1gXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcHJveHlFcnJvck1zZyA9IGBDb3VsZCBub3QgcHJveHkgY29tbWFuZCB0byB0aGUgcmVtb3RlIHNlcnZlci4gT3JpZ2luYWwgZXJyb3I6ICR7ZS5tZXNzYWdlfWA7XG4gICAgICAgIGlmIChDT01QQUNUX0VSUk9SX1BBVFRFUk5TLnNvbWUoKHApID0+IHAudGVzdChlLm1lc3NhZ2UpKSkge1xuICAgICAgICAgIHRoaXMubG9nLmluZm8oZS5tZXNzYWdlKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aGlzLmxvZy5pbmZvKGUuc3RhY2spO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLlByb3h5UmVxdWVzdEVycm9yKHByb3h5RXJyb3JNc2csIGUucmVzcG9uc2U/LmRhdGEsIGUucmVzcG9uc2U/LnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgZ2V0UHJvdG9jb2xGcm9tUmVzQm9keShyZXNPYmopIHtcbiAgICBpZiAoXy5pc0ludGVnZXIocmVzT2JqLnN0YXR1cykpIHtcbiAgICAgIHJldHVybiBNSlNPTldQO1xuICAgIH1cbiAgICBpZiAoIV8uaXNVbmRlZmluZWQocmVzT2JqLnZhbHVlKSkge1xuICAgICAgcmV0dXJuIFczQztcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IHVybFxuICAgKiBAcGFyYW0ge2ltcG9ydCgnQGFwcGl1bS90eXBlcycpLkhUVFBNZXRob2R9IG1ldGhvZFxuICAgKiBAcmV0dXJucyB7c3RyaW5nfHVuZGVmaW5lZH1cbiAgICovXG4gIHJlcXVlc3RUb0NvbW1hbmROYW1lKHVybCwgbWV0aG9kKSB7XG4gICAgLyoqXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1JlZ0V4cH0gcGF0dGVyblxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd8dW5kZWZpbmVkfVxuICAgICAqL1xuICAgIGNvbnN0IGV4dHJhY3RDb21tYW5kTmFtZSA9IChwYXR0ZXJuKSA9PiB7XG4gICAgICBjb25zdCBwYXRoTWF0Y2ggPSBwYXR0ZXJuLmV4ZWModXJsKTtcbiAgICAgIGlmIChwYXRoTWF0Y2gpIHtcbiAgICAgICAgcmV0dXJuIHJvdXRlVG9Db21tYW5kTmFtZShwYXRoTWF0Y2hbMV0sIG1ldGhvZCwgdGhpcy5yZXFCYXNlUGF0aCk7XG4gICAgICB9XG4gICAgfTtcbiAgICBsZXQgY29tbWFuZE5hbWUgPSByb3V0ZVRvQ29tbWFuZE5hbWUodXJsLCBtZXRob2QsIHRoaXMucmVxQmFzZVBhdGgpO1xuICAgIGlmICghY29tbWFuZE5hbWUgJiYgXy5pbmNsdWRlcyh1cmwsIGAke3RoaXMucmVxQmFzZVBhdGh9L3Nlc3Npb24vYCkpIHtcbiAgICAgIGNvbW1hbmROYW1lID0gZXh0cmFjdENvbW1hbmROYW1lKFxuICAgICAgICBuZXcgUmVnRXhwKGAke18uZXNjYXBlUmVnRXhwKHRoaXMucmVxQmFzZVBhdGgpfS9zZXNzaW9uL1teL10rKC4rKWApXG4gICAgICApO1xuICAgIH1cbiAgICBpZiAoIWNvbW1hbmROYW1lICYmIF8uaW5jbHVkZXModXJsLCB0aGlzLnJlcUJhc2VQYXRoKSkge1xuICAgICAgY29tbWFuZE5hbWUgPSBleHRyYWN0Q29tbWFuZE5hbWUobmV3IFJlZ0V4cChgJHtfLmVzY2FwZVJlZ0V4cCh0aGlzLnJlcUJhc2VQYXRoKX0oLy4rKWApKTtcbiAgICB9XG4gICAgcmV0dXJuIGNvbW1hbmROYW1lO1xuICB9XG5cbiAgYXN5bmMgcHJveHlDb21tYW5kKHVybCwgbWV0aG9kLCBib2R5ID0gbnVsbCkge1xuICAgIGNvbnN0IGNvbW1hbmROYW1lID0gdGhpcy5yZXF1ZXN0VG9Db21tYW5kTmFtZSh1cmwsIG1ldGhvZCk7XG4gICAgaWYgKCFjb21tYW5kTmFtZSkge1xuICAgICAgcmV0dXJuIGF3YWl0IHRoaXMucHJveHkodXJsLCBtZXRob2QsIGJvZHkpO1xuICAgIH1cbiAgICB0aGlzLmxvZy5kZWJ1ZyhgTWF0Y2hlZCAnJHt1cmx9JyB0byBjb21tYW5kIG5hbWUgJyR7Y29tbWFuZE5hbWV9J2ApO1xuXG4gICAgcmV0dXJuIGF3YWl0IHRoaXMucHJvdG9jb2xDb252ZXJ0ZXIuY29udmVydEFuZFByb3h5KGNvbW1hbmROYW1lLCB1cmwsIG1ldGhvZCwgYm9keSk7XG4gIH1cblxuICBhc3luYyBjb21tYW5kKHVybCwgbWV0aG9kLCBib2R5ID0gbnVsbCkge1xuICAgIGxldCByZXNwb25zZTtcbiAgICBsZXQgcmVzQm9keU9iajtcbiAgICB0cnkge1xuICAgICAgW3Jlc3BvbnNlLCByZXNCb2R5T2JqXSA9IGF3YWl0IHRoaXMucHJveHlDb21tYW5kKHVybCwgbWV0aG9kLCBib2R5KTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIGlmIChpc0Vycm9yVHlwZShlcnIsIGVycm9ycy5Qcm94eVJlcXVlc3RFcnJvcikpIHtcbiAgICAgICAgdGhyb3cgZXJyLmdldEFjdHVhbEVycm9yKCk7XG4gICAgICB9XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLlVua25vd25FcnJvcihlcnIubWVzc2FnZSk7XG4gICAgfVxuICAgIGNvbnN0IHByb3RvY29sID0gdGhpcy5nZXRQcm90b2NvbEZyb21SZXNCb2R5KHJlc0JvZHlPYmopO1xuICAgIGlmIChwcm90b2NvbCA9PT0gTUpTT05XUCkge1xuICAgICAgLy8gR290IHJlc3BvbnNlIGluIE1KU09OV1AgZm9ybWF0XG4gICAgICBpZiAocmVzcG9uc2Uuc3RhdHVzQ29kZSA9PT0gMjAwICYmIHJlc0JvZHlPYmouc3RhdHVzID09PSAwKSB7XG4gICAgICAgIHJldHVybiByZXNCb2R5T2JqLnZhbHVlO1xuICAgICAgfVxuICAgICAgY29uc3Qgc3RhdHVzID0gcGFyc2VJbnQocmVzQm9keU9iai5zdGF0dXMsIDEwKTtcbiAgICAgIGlmICghaXNOYU4oc3RhdHVzKSAmJiBzdGF0dXMgIT09IDApIHtcbiAgICAgICAgbGV0IG1lc3NhZ2UgPSByZXNCb2R5T2JqLnZhbHVlO1xuICAgICAgICBpZiAoXy5oYXMobWVzc2FnZSwgJ21lc3NhZ2UnKSkge1xuICAgICAgICAgIG1lc3NhZ2UgPSBtZXNzYWdlLm1lc3NhZ2U7XG4gICAgICAgIH1cbiAgICAgICAgdGhyb3cgZXJyb3JGcm9tTUpTT05XUFN0YXR1c0NvZGUoXG4gICAgICAgICAgc3RhdHVzLFxuICAgICAgICAgIF8uaXNFbXB0eShtZXNzYWdlKSA/IGdldFN1bW1hcnlCeUNvZGUoc3RhdHVzKSA6IG1lc3NhZ2VcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKHByb3RvY29sID09PSBXM0MpIHtcbiAgICAgIC8vIEdvdCByZXNwb25zZSBpbiBXM0MgZm9ybWF0XG4gICAgICBpZiAocmVzcG9uc2Uuc3RhdHVzQ29kZSA8IDMwMCkge1xuICAgICAgICByZXR1cm4gcmVzQm9keU9iai52YWx1ZTtcbiAgICAgIH1cbiAgICAgIGlmIChfLmlzUGxhaW5PYmplY3QocmVzQm9keU9iai52YWx1ZSkgJiYgcmVzQm9keU9iai52YWx1ZS5lcnJvcikge1xuICAgICAgICB0aHJvdyBlcnJvckZyb21XM0NKc29uQ29kZShcbiAgICAgICAgICByZXNCb2R5T2JqLnZhbHVlLmVycm9yLFxuICAgICAgICAgIHJlc0JvZHlPYmoudmFsdWUubWVzc2FnZSxcbiAgICAgICAgICByZXNCb2R5T2JqLnZhbHVlLnN0YWNrdHJhY2VcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKHJlc3BvbnNlLnN0YXR1c0NvZGUgPT09IDIwMCkge1xuICAgICAgLy8gVW5rbm93biBwcm90b2NvbC4gS2VlcGluZyBpdCBiZWNhdXNlIG9mIHRoZSBiYWNrd2FyZCBjb21wYXRpYmlsaXR5XG4gICAgICByZXR1cm4gcmVzQm9keU9iajtcbiAgICB9XG4gICAgdGhyb3cgbmV3IGVycm9ycy5Vbmtub3duRXJyb3IoXG4gICAgICBgRGlkIG5vdCBrbm93IHdoYXQgdG8gZG8gd2l0aCByZXNwb25zZSBjb2RlICcke3Jlc3BvbnNlLnN0YXR1c0NvZGV9JyBgICtcbiAgICAgICAgYGFuZCByZXNwb25zZSBib2R5ICcke18udHJ1bmNhdGUoSlNPTi5zdHJpbmdpZnkocmVzQm9keU9iaiksIHtcbiAgICAgICAgICBsZW5ndGg6IDMwMCxcbiAgICAgICAgfSl9J2BcbiAgICApO1xuICB9XG5cbiAgZ2V0U2Vzc2lvbklkRnJvbVVybCh1cmwpIHtcbiAgICBjb25zdCBtYXRjaCA9IHVybC5tYXRjaCgvXFwvc2Vzc2lvblxcLyhbXi9dKykvKTtcbiAgICByZXR1cm4gbWF0Y2ggPyBtYXRjaFsxXSA6IG51bGw7XG4gIH1cblxuICBhc3luYyBwcm94eVJlcVJlcyhyZXEsIHJlcykge1xuICAgIC8vICEgdGhpcyBtZXRob2QgbXVzdCBub3QgdGhyb3cgYW55IGV4Y2VwdGlvbnNcbiAgICAvLyAhIG1ha2Ugc3VyZSB0byBjYWxsIHJlcy5zZW5kIGJlZm9yZSByZXR1cm5cbiAgICBsZXQgc3RhdHVzQ29kZTtcbiAgICBsZXQgcmVzQm9keU9iajtcbiAgICB0cnkge1xuICAgICAgbGV0IHJlc3BvbnNlO1xuICAgICAgW3Jlc3BvbnNlLCByZXNCb2R5T2JqXSA9IGF3YWl0IHRoaXMucHJveHlDb21tYW5kKHJlcS5vcmlnaW5hbFVybCwgcmVxLm1ldGhvZCwgcmVxLmJvZHkpO1xuICAgICAgcmVzLmhlYWRlcnMgPSByZXNwb25zZS5oZWFkZXJzO1xuICAgICAgc3RhdHVzQ29kZSA9IHJlc3BvbnNlLnN0YXR1c0NvZGU7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBbc3RhdHVzQ29kZSwgcmVzQm9keU9ial0gPSBnZXRSZXNwb25zZUZvclczQ0Vycm9yKFxuICAgICAgICBpc0Vycm9yVHlwZShlcnIsIGVycm9ycy5Qcm94eVJlcXVlc3RFcnJvcikgPyBlcnIuZ2V0QWN0dWFsRXJyb3IoKSA6IGVyclxuICAgICAgKTtcbiAgICB9XG4gICAgcmVzLnNldCgnY29udGVudC10eXBlJywgJ2FwcGxpY2F0aW9uL2pzb247IGNoYXJzZXQ9dXRmLTgnKTtcbiAgICBpZiAoIV8uaXNQbGFpbk9iamVjdChyZXNCb2R5T2JqKSkge1xuICAgICAgY29uc3QgZXJyb3IgPSBuZXcgZXJyb3JzLlVua25vd25FcnJvcihcbiAgICAgICAgYFRoZSBkb3duc3RyZWFtIHNlcnZlciByZXNwb25zZSB3aXRoIHRoZSBzdGF0dXMgY29kZSAke3N0YXR1c0NvZGV9IGlzIG5vdCBhIHZhbGlkIEpTT04gb2JqZWN0OiBgICtcbiAgICAgICAgICBfLnRydW5jYXRlKGAke3Jlc0JvZHlPYmp9YCwge2xlbmd0aDogMzAwfSlcbiAgICAgICk7XG4gICAgICBbc3RhdHVzQ29kZSwgcmVzQm9keU9ial0gPSBnZXRSZXNwb25zZUZvclczQ0Vycm9yKGVycm9yKTtcbiAgICB9XG5cbiAgICAvLyBpZiB0aGUgcHJveGllZCByZXNwb25zZSBjb250YWlucyBhIHNlc3Npb25JZCB0aGF0IHRoZSBkb3duc3RyZWFtXG4gICAgLy8gZHJpdmVyIGhhcyBnZW5lcmF0ZWQsIHdlIGRvbid0IHdhbnQgdG8gcmV0dXJuIHRoYXQgdG8gdGhlIGNsaWVudC5cbiAgICAvLyBJbnN0ZWFkLCByZXR1cm4gdGhlIGlkIGZyb20gdGhlIHJlcXVlc3Qgb3IgZnJvbSBjdXJyZW50IHNlc3Npb25cbiAgICBpZiAoXy5oYXMocmVzQm9keU9iaiwgJ3Nlc3Npb25JZCcpKSB7XG4gICAgICBjb25zdCByZXFTZXNzaW9uSWQgPSB0aGlzLmdldFNlc3Npb25JZEZyb21VcmwocmVxLm9yaWdpbmFsVXJsKTtcbiAgICAgIGlmIChyZXFTZXNzaW9uSWQpIHtcbiAgICAgICAgdGhpcy5sb2cuaW5mbyhgUmVwbGFjaW5nIHNlc3Npb25JZCAke3Jlc0JvZHlPYmouc2Vzc2lvbklkfSB3aXRoICR7cmVxU2Vzc2lvbklkfWApO1xuICAgICAgICByZXNCb2R5T2JqLnNlc3Npb25JZCA9IHJlcVNlc3Npb25JZDtcbiAgICAgIH0gZWxzZSBpZiAodGhpcy5zZXNzaW9uSWQpIHtcbiAgICAgICAgdGhpcy5sb2cuaW5mbyhgUmVwbGFjaW5nIHNlc3Npb25JZCAke3Jlc0JvZHlPYmouc2Vzc2lvbklkfSB3aXRoICR7dGhpcy5zZXNzaW9uSWR9YCk7XG4gICAgICAgIHJlc0JvZHlPYmouc2Vzc2lvbklkID0gdGhpcy5zZXNzaW9uSWQ7XG4gICAgICB9XG4gICAgfVxuICAgIHJlc0JvZHlPYmoudmFsdWUgPSBmb3JtYXRSZXNwb25zZVZhbHVlKHJlc0JvZHlPYmoudmFsdWUpO1xuICAgIHJlcy5zdGF0dXMoc3RhdHVzQ29kZSkuc2VuZChKU09OLnN0cmluZ2lmeShmb3JtYXRTdGF0dXMocmVzQm9keU9iaikpKTtcbiAgfVxufVxuXG5leHBvcnQge0pXUHJveHl9O1xuZXhwb3J0IGRlZmF1bHQgSldQcm94eTtcblxuLyoqXG4gKiBAdHlwZWRlZiB7RXJyb3IgJiB7cmVzcG9uc2U6IHtkYXRhOiBpbXBvcnQoJ3R5cGUtZmVzdCcpLkpzb25PYmplY3QsIHN0YXR1czogaW1wb3J0KCdodHRwLXN0YXR1cy1jb2RlcycpLlN0YXR1c0NvZGVzfX19IFByb3h5RXJyb3JcbiAqL1xuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7QUFBQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFPQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7OztBQUVBLE1BQU1BLFdBQVcsR0FBR0MsZUFBQSxDQUFPQyxTQUFQLENBQWlCLFVBQWpCLENBQXBCOztBQUNBLE1BQU1DLHVCQUF1QixHQUFHLE1BQWhDO0FBQ0EsTUFBTUMsc0JBQXNCLEdBQUcsQ0FBQyxrQkFBRCxFQUFxQixnQkFBckIsQ0FBL0I7QUFFQSxNQUFNO0VBQUNDLE9B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
|
|
377
|
+
exports.default = JWProxy;
|
|
378
|
+
/**
|
|
379
|
+
* @typedef {Error & {response: {data: import('type-fest').JsonObject, status: import('http-status-codes').StatusCodes}}} ProxyError
|
|
380
|
+
*/
|
|
381
|
+
//# sourceMappingURL=proxy.js.map
|