Files
appium/lib/server/proxy.js

112 lines
3.7 KiB
JavaScript

"use strict";
var _s = require('underscore.string')
, logger = require('./logger.js').get('appium')
, status = require('./status.js')
, doRequest = require('../devices/common.js').doRequest
, respondError = require('./responses.js').respondError
, _ = require('underscore')
, safely = require('./helpers').safely;
module.exports.shouldProxy = function (req) {
if (req.device === null) return false;
if (!req.device.isProxy) return false;
var deviceAvoids = req.device.avoidProxy || [];
var avoid = [
['POST', new RegExp('^/wd/hub/session$')]
, ['DELETE', new RegExp('^/wd/hub/session/[^/]+$')]
].concat(deviceAvoids);
var method = req.method.toUpperCase();
var path = req.originalUrl;
var shouldAvoid = false;
// check for POST /execute mobile:
if (method === 'POST' &&
new RegExp('^/wd/hub/session/.+/execute$').test(path) &&
_s.startsWith(req.body.script, "mobile: ")) {
shouldAvoid = true;
}
_.each(avoid, function (pathToAvoid) {
if (method === pathToAvoid[0] && pathToAvoid[1].exec(path)) {
shouldAvoid = true;
}
});
return !shouldAvoid;
};
module.exports.doProxy = function (req, res) {
if (req.device.proxyReqRes) {
// this section is triggered when we have defined the proxy device to use
// the appium-jsonwp-proxy method proxyReqRes. Ultimately we'll be moving
// everything to this paradigm and will delete the code after this block.
// proxyReqRes might be a promise or a callback-based function, so handle
// both
var handler = function (err) {
logger.error(err.message);
};
var p = req.device.proxyReqRes(req, res, handler);
if (p.catch) {
p.catch(handler);
}
return;
}
logger.debug("Proxying command to " + req.device.proxyHost + ":" +
req.device.proxyPort);
var sessRe = new RegExp('^/wd/hub/session/([^/]+)');
var sessionRegxMatch = sessRe.exec(req.originalUrl);
var newPath, origSessId = null;
// there might be no session id in the orig. req.
if (sessionRegxMatch) {
origSessId = sessionRegxMatch[1];
var sessId = req.device.proxySessionId ? req.device.proxySessionId :
origSessId;
newPath = req.originalUrl.replace(origSessId, sessId);
} else {
newPath = req.originalUrl;
}
var url = 'http://' + req.device.proxyHost + ':' + req.device.proxyPort +
newPath;
doRequest(url, req.method.toUpperCase(), req.body,
req.headers['content-type'], function (err, response, body) {
if (typeof body === "string") {
try {
body = JSON.parse(body);
} catch (e) {}
}
if (err) {
return respondError(req, res, status.codes.UnknownError.code,
"Did not successfully proxy server command");
}
if (body && body.value) {
var resStatusCode = body.status;
if (resStatusCode !== 0) {
var resErrorMessage = body.value.message;
return respondError(req, res, resStatusCode, resErrorMessage);
}
}
var sbody = body ? JSON.stringify(body).slice(0, 10000) : body;
logger.debug("Proxied response received with status " +
response.statusCode + ": " +
sbody);
// if the proxied response contains a sessionId that the downstream
// driver has generated, we don't want to return that to the client.
// Instead, return the id for the current appium session
if (body && body.sessionId && origSessId) {
body.sessionId = origSessId;
}
safely(req, function () {
res.headers = response.headers;
res.set('Content-Type', response.headers['content-type']);
res.status(response.statusCode).send(body);
});
});
};