@appium/base-driver 10.0.0-beta.0 → 10.0.0-beta.1
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/README.md +0 -8
- package/build/lib/basedriver/capabilities.d.ts.map +1 -1
- package/build/lib/basedriver/capabilities.js +2 -4
- package/build/lib/basedriver/capabilities.js.map +1 -1
- package/build/lib/basedriver/commands/timeout.js +7 -25
- package/build/lib/basedriver/commands/timeout.js.map +1 -1
- package/build/lib/basedriver/core.d.ts +0 -8
- package/build/lib/basedriver/core.d.ts.map +1 -1
- package/build/lib/basedriver/core.js +8 -18
- package/build/lib/basedriver/core.js.map +1 -1
- package/build/lib/basedriver/driver.js +2 -2
- package/build/lib/basedriver/driver.js.map +1 -1
- package/build/lib/basedriver/helpers.d.ts +9 -1
- package/build/lib/basedriver/helpers.d.ts.map +1 -1
- package/build/lib/basedriver/helpers.js +56 -142
- package/build/lib/basedriver/helpers.js.map +1 -1
- package/build/lib/basedriver/validation.d.ts +7 -0
- package/build/lib/basedriver/validation.d.ts.map +1 -0
- package/build/lib/basedriver/validation.js +130 -0
- package/build/lib/basedriver/validation.js.map +1 -0
- package/build/lib/express/middleware.d.ts +0 -6
- package/build/lib/express/middleware.d.ts.map +1 -1
- package/build/lib/express/middleware.js +28 -60
- package/build/lib/express/middleware.js.map +1 -1
- package/build/lib/express/server.d.ts.map +1 -1
- package/build/lib/express/server.js +0 -1
- package/build/lib/express/server.js.map +1 -1
- package/build/lib/helpers/capabilities.d.ts +13 -6
- package/build/lib/helpers/capabilities.d.ts.map +1 -1
- package/build/lib/helpers/capabilities.js +7 -0
- package/build/lib/helpers/capabilities.js.map +1 -1
- package/build/lib/index.d.ts +1 -0
- package/build/lib/index.d.ts.map +1 -1
- package/build/lib/index.js +3 -1
- package/build/lib/index.js.map +1 -1
- package/build/lib/jsonwp-proxy/proxy.d.ts +0 -8
- package/build/lib/jsonwp-proxy/proxy.d.ts.map +1 -1
- package/build/lib/jsonwp-proxy/proxy.js +7 -38
- package/build/lib/jsonwp-proxy/proxy.js.map +1 -1
- package/build/lib/protocol/errors.d.ts +171 -277
- package/build/lib/protocol/errors.d.ts.map +1 -1
- package/build/lib/protocol/errors.js +201 -421
- package/build/lib/protocol/errors.js.map +1 -1
- package/build/lib/protocol/helpers.d.ts +6 -6
- package/build/lib/protocol/helpers.d.ts.map +1 -1
- package/build/lib/protocol/helpers.js +11 -7
- package/build/lib/protocol/helpers.js.map +1 -1
- package/build/lib/protocol/index.d.ts +2 -1
- package/build/lib/protocol/index.d.ts.map +1 -1
- package/build/lib/protocol/index.js +2 -1
- package/build/lib/protocol/index.js.map +1 -1
- package/build/lib/protocol/protocol.d.ts +5 -0
- package/build/lib/protocol/protocol.d.ts.map +1 -1
- package/build/lib/protocol/protocol.js +23 -23
- package/build/lib/protocol/protocol.js.map +1 -1
- package/build/lib/protocol/routes.d.ts +14 -715
- package/build/lib/protocol/routes.d.ts.map +1 -1
- package/build/lib/protocol/routes.js +28 -487
- package/build/lib/protocol/routes.js.map +1 -1
- package/build/lib/protocol/validators.d.ts +4 -7
- package/build/lib/protocol/validators.d.ts.map +1 -1
- package/build/lib/protocol/validators.js +4 -21
- package/build/lib/protocol/validators.js.map +1 -1
- package/lib/basedriver/capabilities.ts +2 -4
- package/lib/basedriver/commands/timeout.ts +11 -34
- package/lib/basedriver/core.ts +10 -19
- package/lib/basedriver/driver.ts +3 -3
- package/lib/basedriver/helpers.js +61 -167
- package/lib/basedriver/validation.ts +145 -0
- package/lib/express/middleware.js +32 -70
- package/lib/express/server.js +0 -2
- package/lib/helpers/capabilities.js +9 -4
- package/lib/index.js +2 -0
- package/lib/jsonwp-proxy/proxy.js +8 -45
- package/lib/protocol/{errors.js → errors.ts} +322 -436
- package/lib/protocol/helpers.js +12 -8
- package/lib/protocol/index.js +8 -1
- package/lib/protocol/protocol.js +25 -23
- package/lib/protocol/routes.js +30 -497
- package/lib/protocol/validators.ts +19 -0
- package/package.json +10 -11
- package/build/lib/basedriver/desired-caps.d.ts +0 -5
- package/build/lib/basedriver/desired-caps.d.ts.map +0 -1
- package/build/lib/basedriver/desired-caps.js +0 -92
- package/build/lib/basedriver/desired-caps.js.map +0 -1
- package/lib/basedriver/README.md +0 -36
- package/lib/basedriver/desired-caps.js +0 -103
- package/lib/express/README.md +0 -59
- package/lib/jsonwp-proxy/README.md +0 -52
- package/lib/jsonwp-status/README.md +0 -20
- package/lib/protocol/README.md +0 -100
- package/lib/protocol/validators.js +0 -38
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import type { Constraint } from '@appium/types';
|
|
2
|
+
import log from './logger';
|
|
3
|
+
import _ from 'lodash';
|
|
4
|
+
|
|
5
|
+
export class Validator {
|
|
6
|
+
private readonly _validators: Record<
|
|
7
|
+
keyof Constraint,
|
|
8
|
+
(value: any, options?: any, key?: string) => string | null
|
|
9
|
+
> = {
|
|
10
|
+
isString: (value: any, options?: any): string | null => {
|
|
11
|
+
if (_.isUndefined(value) || _.isNil(options)) {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
if (_.isString(value)) {
|
|
16
|
+
return options ? null : 'must not be of type string';
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return options ? 'must be of type string' : null;
|
|
20
|
+
},
|
|
21
|
+
isNumber: (value: any, options?: any): string | null => {
|
|
22
|
+
if (_.isUndefined(value) || _.isNil(options)) {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (_.isNumber(value)) {
|
|
27
|
+
return options ? null : 'must not be of type number';
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// allow a string value
|
|
31
|
+
if (options && _.isString(value) && !isNaN(Number(value))) {
|
|
32
|
+
log.warn('Number capability passed in as string. Functionality may be compromised.');
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return options ? 'must be of type number' : null;
|
|
37
|
+
},
|
|
38
|
+
isBoolean: (value: any, options?: any): string | null => {
|
|
39
|
+
if (_.isUndefined(value) || _.isNil(options)) {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (_.isBoolean(value)) {
|
|
44
|
+
return options ? null : 'must not be of type boolean';
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// allow a string value
|
|
48
|
+
if (options && _.isString(value) && ['true', 'false', ''].includes(value)) {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return options ? 'must be of type boolean' : null;
|
|
53
|
+
},
|
|
54
|
+
isObject: (value: any, options?: any): string | null => {
|
|
55
|
+
if (_.isUndefined(value) || _.isNil(options)) {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (_.isPlainObject(value)) {
|
|
60
|
+
return options ? null : 'must not be a plain object';
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return options ? 'must be a plain object' : null;
|
|
64
|
+
},
|
|
65
|
+
isArray: (value: any, options?: any): string | null => {
|
|
66
|
+
if (_.isUndefined(value) || _.isNil(options)) {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (_.isArray(value)) {
|
|
71
|
+
return options ? null : 'must not be of type array';
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return options ? 'must be of type array' : null;
|
|
75
|
+
},
|
|
76
|
+
deprecated: (value: any, options?: any, key?: string): string | null => {
|
|
77
|
+
if (!_.isUndefined(value) && options) {
|
|
78
|
+
log.warn(
|
|
79
|
+
`The '${key}' capability has been deprecated and must not be used anymore. ` +
|
|
80
|
+
`Please check the driver documentation for possible alternatives.`
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
return null;
|
|
84
|
+
},
|
|
85
|
+
inclusion: (value: any, options?: any): string | null => {
|
|
86
|
+
if (_.isUndefined(value) || !options) {
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
const optionsArr = _.isArray(options) ? options : [options];
|
|
90
|
+
if (optionsArr.some((opt) => opt === value)) {
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
return `must be contained by ${JSON.stringify(optionsArr)}`;
|
|
94
|
+
},
|
|
95
|
+
inclusionCaseInsensitive: (value: any, options?: any): string | null => {
|
|
96
|
+
if (_.isUndefined(value) || !options) {
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
const optionsArr = _.isArray(options) ? options : [options];
|
|
100
|
+
if (optionsArr.some((opt) => _.toLower(opt) === _.toLower(value))) {
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
return `must be contained by ${JSON.stringify(optionsArr)}`;
|
|
104
|
+
},
|
|
105
|
+
presence: (value: any, options?: any): string | null => {
|
|
106
|
+
if (_.isUndefined(value) && options) {
|
|
107
|
+
return 'is required to be present';
|
|
108
|
+
}
|
|
109
|
+
if (
|
|
110
|
+
!options?.allowEmpty &&
|
|
111
|
+
((!_.isUndefined(value) && _.isEmpty(value)) || (_.isString(value) && !_.trim(value)))
|
|
112
|
+
) {
|
|
113
|
+
return 'must not be empty or blank';
|
|
114
|
+
}
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
validate(values: Record<string, any>, constraints: Record<string, Constraint>): Record<string, string[]> | null {
|
|
120
|
+
const result: Record<string, string[]> = {};
|
|
121
|
+
for (const [key, constraint] of _.toPairs(constraints)) {
|
|
122
|
+
const value = values[key];
|
|
123
|
+
for (const [validatorName, options] of _.toPairs(constraint)) {
|
|
124
|
+
if (!(validatorName in this._validators)) {
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const validationError = this._validators[validatorName](value, options, key);
|
|
129
|
+
if (_.isNil(validationError)) {
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (key in result) {
|
|
134
|
+
result[key].push(validationError);
|
|
135
|
+
} else {
|
|
136
|
+
result[key] = [validationError];
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return _.isEmpty(result) ? null : result;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export const validator = new Validator();
|
|
@@ -5,6 +5,9 @@ export {handleIdempotency} from './idempotency';
|
|
|
5
5
|
import {match} from 'path-to-regexp';
|
|
6
6
|
import {util} from '@appium/support';
|
|
7
7
|
import {calcSignature} from '../helpers/session';
|
|
8
|
+
import {getResponseForW3CError} from '../protocol/errors';
|
|
9
|
+
|
|
10
|
+
const SESSION_ID_PATTERN = /\/session\/([^/]+)/;
|
|
8
11
|
|
|
9
12
|
/**
|
|
10
13
|
*
|
|
@@ -14,20 +17,16 @@ import {calcSignature} from '../helpers/session';
|
|
|
14
17
|
* @returns {any}
|
|
15
18
|
*/
|
|
16
19
|
export function allowCrossDomain(req, res, next) {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
);
|
|
20
|
+
res.header('Access-Control-Allow-Origin', '*');
|
|
21
|
+
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, OPTIONS, DELETE');
|
|
22
|
+
res.header(
|
|
23
|
+
'Access-Control-Allow-Headers',
|
|
24
|
+
'Cache-Control, Pragma, Origin, X-Requested-With, Content-Type, Accept, User-Agent'
|
|
25
|
+
);
|
|
24
26
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
}
|
|
29
|
-
} catch (err) {
|
|
30
|
-
log.error(`Unexpected error: ${err.stack}`);
|
|
27
|
+
// need to respond 200 to OPTIONS
|
|
28
|
+
if ('OPTIONS' === req.method) {
|
|
29
|
+
return res.sendStatus(200);
|
|
31
30
|
}
|
|
32
31
|
next();
|
|
33
32
|
}
|
|
@@ -50,26 +49,6 @@ export function allowCrossDomainAsyncExecute(basePath) {
|
|
|
50
49
|
};
|
|
51
50
|
}
|
|
52
51
|
|
|
53
|
-
/**
|
|
54
|
-
*
|
|
55
|
-
* @param {string} basePath
|
|
56
|
-
* @returns {import('express').RequestHandler}
|
|
57
|
-
*/
|
|
58
|
-
export function fixPythonContentType(basePath) {
|
|
59
|
-
return (req, res, next) => {
|
|
60
|
-
// hack because python client library gives us wrong content-type
|
|
61
|
-
if (
|
|
62
|
-
new RegExp(`^${_.escapeRegExp(basePath)}`).test(req.path) &&
|
|
63
|
-
/^Python/.test(req.headers['user-agent'] ?? '')
|
|
64
|
-
) {
|
|
65
|
-
if (req.headers['content-type'] === 'application/x-www-form-urlencoded') {
|
|
66
|
-
req.headers['content-type'] = 'application/json; charset=utf-8';
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
next();
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
|
|
73
52
|
/**
|
|
74
53
|
*
|
|
75
54
|
* @param {import('express').Request} req
|
|
@@ -78,12 +57,17 @@ export function fixPythonContentType(basePath) {
|
|
|
78
57
|
* @returns {any}
|
|
79
58
|
*/
|
|
80
59
|
export function handleLogContext(req, res, next) {
|
|
81
|
-
const requestId = util.uuidV4();
|
|
60
|
+
const requestId = fetchHeaderValue(req, 'x-request-id') || util.uuidV4();
|
|
82
61
|
|
|
83
62
|
const sessionId = SESSION_ID_PATTERN.exec(req.url)?.[1];
|
|
84
63
|
const sessionInfo = sessionId ? {sessionId, sessionSignature: calcSignature(sessionId)} : {};
|
|
64
|
+
const isSensitiveHeaderValue = fetchHeaderValue(req, 'x-appium-is-sensitive');
|
|
85
65
|
|
|
86
|
-
log.updateAsyncContext({
|
|
66
|
+
log.updateAsyncContext({
|
|
67
|
+
requestId,
|
|
68
|
+
...sessionInfo,
|
|
69
|
+
isSensitive: ['true', '1', 'yes'].includes(_.toLower(isSensitiveHeaderValue)),
|
|
70
|
+
}, true);
|
|
87
71
|
|
|
88
72
|
return next();
|
|
89
73
|
}
|
|
@@ -142,19 +126,8 @@ export function catchAllHandler(err, req, res, next) {
|
|
|
142
126
|
}
|
|
143
127
|
|
|
144
128
|
log.error(`Uncaught error: ${err.message}`);
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
res.status(error.w3cStatus()).json(
|
|
148
|
-
patchWithSessionId(req, {
|
|
149
|
-
status: error.code(),
|
|
150
|
-
value: {
|
|
151
|
-
error: error.error(),
|
|
152
|
-
message: `An unknown server-side error occurred while processing the command: ${err.message}`,
|
|
153
|
-
stacktrace: err.stack,
|
|
154
|
-
},
|
|
155
|
-
})
|
|
156
|
-
);
|
|
157
|
-
log.error(err);
|
|
129
|
+
const [status, body] = getResponseForW3CError(err);
|
|
130
|
+
res.status(status).json(body);
|
|
158
131
|
}
|
|
159
132
|
|
|
160
133
|
/**
|
|
@@ -163,28 +136,17 @@ export function catchAllHandler(err, req, res, next) {
|
|
|
163
136
|
*/
|
|
164
137
|
export function catch404Handler(req, res) {
|
|
165
138
|
log.debug(`No route found for ${req.url}`);
|
|
166
|
-
const
|
|
167
|
-
res.status(
|
|
168
|
-
patchWithSessionId(req, {
|
|
169
|
-
status: error.code(),
|
|
170
|
-
value: {
|
|
171
|
-
error: error.error(),
|
|
172
|
-
message:
|
|
173
|
-
'The requested resource could not be found, or a request was ' +
|
|
174
|
-
'received using an HTTP method that is not supported by the mapped ' +
|
|
175
|
-
'resource',
|
|
176
|
-
stacktrace: '',
|
|
177
|
-
},
|
|
178
|
-
})
|
|
179
|
-
);
|
|
139
|
+
const [status, body] = getResponseForW3CError(new errors.UnknownCommandError());
|
|
140
|
+
res.status(status).json(body);
|
|
180
141
|
}
|
|
181
142
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
143
|
+
/**
|
|
144
|
+
* @param {import('express').Request} req
|
|
145
|
+
* @param {string} name
|
|
146
|
+
* @returns {string | undefined}
|
|
147
|
+
*/
|
|
148
|
+
function fetchHeaderValue(req, name) {
|
|
149
|
+
return _.isArray(req.headers[name])
|
|
150
|
+
? req.headers[name][0]
|
|
151
|
+
: req.headers[name];
|
|
190
152
|
}
|
package/lib/express/server.js
CHANGED
|
@@ -9,7 +9,6 @@ import log from './logger';
|
|
|
9
9
|
import {startLogFormatter, endLogFormatter} from './express-logging';
|
|
10
10
|
import {
|
|
11
11
|
allowCrossDomain,
|
|
12
|
-
fixPythonContentType,
|
|
13
12
|
defaultToJSONContentType,
|
|
14
13
|
catchAllHandler,
|
|
15
14
|
allowCrossDomainAsyncExecute,
|
|
@@ -172,7 +171,6 @@ export function configureServer({
|
|
|
172
171
|
app.use(allowCrossDomainAsyncExecute(basePath));
|
|
173
172
|
}
|
|
174
173
|
app.use(handleIdempotency);
|
|
175
|
-
app.use(fixPythonContentType(basePath));
|
|
176
174
|
app.use(defaultToJSONContentType);
|
|
177
175
|
app.use(bodyParser.urlencoded({extended: true}));
|
|
178
176
|
app.use(methodOverride());
|
|
@@ -2,7 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
import _ from 'lodash';
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
/**
|
|
6
|
+
* Determine whether the given agument is valid
|
|
7
|
+
* W3C capabilities instance.
|
|
8
|
+
*
|
|
9
|
+
* @param {any} caps
|
|
10
|
+
* @returns {caps is import('@appium/types').W3CCapabilities}
|
|
11
|
+
*/
|
|
12
|
+
export function isW3cCaps(caps) {
|
|
6
13
|
if (!_.isPlainObject(caps)) {
|
|
7
14
|
return false;
|
|
8
15
|
}
|
|
@@ -32,7 +39,7 @@ function isW3cCaps(caps) {
|
|
|
32
39
|
* @param {AppiumLogger} log
|
|
33
40
|
* @returns {Capabilities<C>}
|
|
34
41
|
*/
|
|
35
|
-
function fixCaps(oldCaps, desiredCapConstraints, log) {
|
|
42
|
+
export function fixCaps(oldCaps, desiredCapConstraints, log) {
|
|
36
43
|
let caps = _.clone(oldCaps);
|
|
37
44
|
|
|
38
45
|
// boolean capabilities can be passed in as strings 'false' and 'true'
|
|
@@ -73,8 +80,6 @@ function fixCaps(oldCaps, desiredCapConstraints, log) {
|
|
|
73
80
|
return caps;
|
|
74
81
|
}
|
|
75
82
|
|
|
76
|
-
export {isW3cCaps, fixCaps};
|
|
77
|
-
|
|
78
83
|
/**
|
|
79
84
|
* @typedef {import('@appium/types').Constraints} Constraints
|
|
80
85
|
* @typedef {import('@appium/types').AppiumLogger} AppiumLogger
|
package/lib/index.js
CHANGED
|
@@ -54,6 +54,8 @@ export {BIDI_COMMANDS} from './protocol/bidi-commands';
|
|
|
54
54
|
|
|
55
55
|
export {generateDriverLogPrefix} from './basedriver/helpers';
|
|
56
56
|
|
|
57
|
+
export {isW3cCaps} from './helpers/capabilities';
|
|
58
|
+
|
|
57
59
|
/**
|
|
58
60
|
* @typedef {import('./express/server').ServerOpts} ServerOpts
|
|
59
61
|
*/
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
import {isSessionCommand, routeToCommandName} from '../protocol';
|
|
12
12
|
import {MAX_LOG_BODY_LENGTH, DEFAULT_BASE_PATH, PROTOCOLS} from '../constants';
|
|
13
13
|
import ProtocolConverter from './protocol-converter';
|
|
14
|
-
import {formatResponseValue,
|
|
14
|
+
import {formatResponseValue, ensureW3cResponse} from '../protocol/helpers';
|
|
15
15
|
import http from 'http';
|
|
16
16
|
import https from 'https';
|
|
17
17
|
import { match as pathToRegexMatch } from 'path-to-regexp';
|
|
@@ -290,37 +290,6 @@ export class JWProxy {
|
|
|
290
290
|
}
|
|
291
291
|
}
|
|
292
292
|
|
|
293
|
-
/**
|
|
294
|
-
* @deprecated This method is not used anymore and will be removed
|
|
295
|
-
*
|
|
296
|
-
* @param {string} url
|
|
297
|
-
* @param {import('@appium/types').HTTPMethod} method
|
|
298
|
-
* @returns {string|undefined}
|
|
299
|
-
*/
|
|
300
|
-
requestToCommandName(url, method) {
|
|
301
|
-
/**
|
|
302
|
-
*
|
|
303
|
-
* @param {RegExp} pattern
|
|
304
|
-
* @returns {string|undefined}
|
|
305
|
-
*/
|
|
306
|
-
const extractCommandName = (pattern) => {
|
|
307
|
-
const pathMatch = pattern.exec(url);
|
|
308
|
-
if (pathMatch) {
|
|
309
|
-
return routeToCommandName(pathMatch[1], method, this.reqBasePath);
|
|
310
|
-
}
|
|
311
|
-
};
|
|
312
|
-
let commandName = routeToCommandName(url, method, this.reqBasePath);
|
|
313
|
-
if (!commandName && _.includes(url, `${this.reqBasePath}/session/`)) {
|
|
314
|
-
commandName = extractCommandName(
|
|
315
|
-
new RegExp(`${_.escapeRegExp(this.reqBasePath)}/session/[^/]+(.+)`)
|
|
316
|
-
);
|
|
317
|
-
}
|
|
318
|
-
if (!commandName && _.includes(url, this.reqBasePath)) {
|
|
319
|
-
commandName = extractCommandName(new RegExp(`${_.escapeRegExp(this.reqBasePath)}(/.+)`));
|
|
320
|
-
}
|
|
321
|
-
return commandName;
|
|
322
|
-
}
|
|
323
|
-
|
|
324
293
|
/**
|
|
325
294
|
*
|
|
326
295
|
* @param {string} url
|
|
@@ -428,18 +397,13 @@ export class JWProxy {
|
|
|
428
397
|
/** @type {import('@appium/types').HTTPMethod} */ (req.method),
|
|
429
398
|
req.body
|
|
430
399
|
);
|
|
431
|
-
for (const [name, value] of _.toPairs(response.headers)) {
|
|
432
|
-
if (!_.isNil(value)) {
|
|
433
|
-
res.setHeader(name, _.isBoolean(value) ? String(value) : value);
|
|
434
|
-
}
|
|
435
|
-
}
|
|
436
400
|
statusCode = response.statusCode;
|
|
437
401
|
} catch (err) {
|
|
438
402
|
[statusCode, resBodyObj] = getResponseForW3CError(
|
|
439
403
|
isErrorType(err, errors.ProxyRequestError) ? err.getActualError() : err
|
|
440
404
|
);
|
|
441
405
|
}
|
|
442
|
-
res.
|
|
406
|
+
res.setHeader('content-type', 'application/json; charset=utf-8');
|
|
443
407
|
if (!_.isPlainObject(resBodyObj)) {
|
|
444
408
|
const error = new errors.UnknownError(
|
|
445
409
|
`The downstream server response with the status code ${statusCode} is not a valid JSON object: ` +
|
|
@@ -462,7 +426,7 @@ export class JWProxy {
|
|
|
462
426
|
}
|
|
463
427
|
}
|
|
464
428
|
resBodyObj.value = formatResponseValue(resBodyObj.value);
|
|
465
|
-
res.status(statusCode).
|
|
429
|
+
res.status(statusCode).json(ensureW3cResponse(resBodyObj));
|
|
466
430
|
}
|
|
467
431
|
|
|
468
432
|
/**
|
|
@@ -503,12 +467,11 @@ export class JWProxy {
|
|
|
503
467
|
pathname = pathname.replace('/wd/hub', '');
|
|
504
468
|
}
|
|
505
469
|
}
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
);
|
|
470
|
+
let result = pathname;
|
|
471
|
+
if (match) {
|
|
472
|
+
result = _.isArray(match.params?.command) ? `/${match.params.command.join('/')}` : '';
|
|
473
|
+
}
|
|
474
|
+
return _.trimEnd(result, '/');
|
|
512
475
|
}
|
|
513
476
|
}
|
|
514
477
|
|