Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 15 additions & 4 deletions src/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,17 @@ import http from 'http';
import { Application } from 'express';
import { CliArg, ISessionCapability, MockConfig, RecordConfig, RequestInfo, ReplayConfig, SniffConfig } from './types';
import _ from 'lodash';
import { configureWifiProxy, isRealDevice } from './utils/adb';
import { configureWifiProxy, isRealDevice, getGlobalProxyValue } from './utils/adb';
import { cleanUpProxyServer, sanitizeMockConfig, setupProxyServer } from './utils/proxy';
import proxyCache from './proxy-cache';
import logger from './logger';
import log from './logger';
import { ProxyOptions } from './proxy';

export class AppiumInterceptorPlugin extends BasePlugin {

private previousGlobalProxy: ProxyOptions = {} as ProxyOptions

static executeMethodMap = {
'interceptor: addMock': {
command: 'addMock',
Expand Down Expand Up @@ -98,8 +102,13 @@ export class AppiumInterceptorPlugin extends BasePlugin {
return response;
}
const realDevice = await isRealDevice(adb, deviceUDID);

this.previousGlobalProxy = await getGlobalProxyValue(adb, deviceUDID)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Storing the previous proxy state in the class instance can lead to issues when tests run in parallel.

A better approach is to store the current proxy URL within the session’s proxy object, ensuring it remains unique to each device session.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed - previous proxy state saved in current proxy object

log.info(`Current proxy: ${this.previousGlobalProxy}}`)


const proxy = await setupProxyServer(sessionId, deviceUDID, realDevice);
await configureWifiProxy(adb, deviceUDID, realDevice, proxy);
await configureWifiProxy(adb, deviceUDID, realDevice, proxy.options);
proxyCache.add(sessionId, proxy);
}
log.info("Creating session for appium interceptor");
Expand All @@ -110,7 +119,9 @@ export class AppiumInterceptorPlugin extends BasePlugin {
const proxy = proxyCache.get(sessionId);
if (proxy) {
const adb = driver.sessions[sessionId]?.adb;
await configureWifiProxy(adb, proxy.deviceUDID, false);

log.info(`Set previous proxy settings`)
await configureWifiProxy(adb, proxy.deviceUDID, false, this.previousGlobalProxy);
await cleanUpProxyServer(proxy);
}
return next();
Expand All @@ -122,7 +133,7 @@ export class AppiumInterceptorPlugin extends BasePlugin {
const proxy = proxyCache.get(sessionId);
if (proxy) {
const adb = driver.sessions[sessionId]?.adb;
await configureWifiProxy(adb, proxy.deviceUDID, false);
await configureWifiProxy(adb, proxy.deviceUDID, false, this.previousGlobalProxy);
await cleanUpProxyServer(proxy);
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/proxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export class Proxy {
this._replayStarted = true;
}

constructor(private readonly options: ProxyOptions) {
constructor(public readonly options: ProxyOptions) {
this.httpProxy = new HttpProxy();
this.recordingManager = new RecordingManager(options);
addDefaultMocks(this);
Expand Down
2 changes: 1 addition & 1 deletion src/scripts/test-connection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ async function verifyDeviceConnection(adb: ADBInstance, udid: UDID) {
const realDevice = await isRealDevice(adb, udid);
const proxy = await setupProxyServer(uuid(), udid, realDevice);
addMock(proxy);
await configureWifiProxy(adb, udid, realDevice, proxy);
await configureWifiProxy(adb, udid, realDevice, proxy.options);
await openUrl(adb, udid, MOCK_BACKEND_URL);
}

Expand Down
40 changes: 37 additions & 3 deletions src/utils/adb.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import ADB from 'appium-adb';
import { Proxy } from '../proxy';
import { Proxy, ProxyOptions } from '../proxy';

export type ADBInstance = ADB;
export type UDID = string;
Expand Down Expand Up @@ -29,10 +29,10 @@ export async function configureWifiProxy(
adb: ADBInstance,
udid: UDID,
realDevice: boolean,
proxy?: Proxy
proxy?: ProxyOptions
): Promise<string> {
try {
const host = proxy ? `${proxy.ip}:${proxy.port}` : ':0';
const host = proxy?.ip ? `${proxy.ip}:${proxy.port}` : ':0';

if (realDevice && proxy) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we also update the condition here to check if the proxy has a valid ip/port property?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Global proxies are defined in the "host:port" format, so I don’t think any additional checks are necessary.

await adbExecWithDevice(adb, udid, ['reverse', `tcp:${proxy.port}`, `tcp:${proxy.port}`]);
Expand All @@ -51,6 +51,40 @@ export async function configureWifiProxy(
}
}

export async function getGlobalProxyValue(
adb: ADBInstance,
udid: UDID
): Promise<ProxyOptions> {
try {

const proxy = await adbExecWithDevice(adb, udid, [
'shell',
'settings',
'get',
'global',
'http_proxy'
])

if(proxy == ":0" || proxy == "null") {
return {
port: 0
} as ProxyOptions
}

const [ip, portStr] = proxy.split(":");
const port = Number(portStr);

return {
ip: ip,
port: port
} as ProxyOptions

} catch (error: any) {
throw new Error(`Error get global proxy value ${udid}: ${error.message}`);
}
}


export async function openUrl(adb: ADBInstance, udid: UDID, url: string) {
await adbExecWithDevice(adb, udid, [
'shell',
Expand Down