"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); }); }); };