Skip to content

Commit ee6d020

Browse files
authored
fix: add new command to get proxy state (#84)
- Add new entry in executeMethodMap (plugin.ts) - Implement new function getProxyState (plugin.ts) : it returns a json object containing the proxy server state + the current proxy conf on the adb device - Add new function getAdbReverseTunnels (adb.ts) that allow to list active reverse tunnels - Update readme
1 parent 32f9b85 commit ee6d020

File tree

3 files changed

+95
-1
lines changed

3 files changed

+95
-1
lines changed

docs/commands.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,3 +398,36 @@ Below code shows how to add the mock and get the id
398398
new HashMap() {{put("config", config); }});
399399
400400
```
401+
402+
### interceptor: getProxyState
403+
404+
Returns the current health and configuration state of both the interceptor proxy and the ADB device under test. This is useful for diagnostic purposes to verify if the proxy is running correctly and if the device is properly connected via ADB reverse tunnels. It can be used to monitor proxy state on client side.
405+
406+
#### Example:
407+
408+
```javascript
409+
const state = await driver.execute("interceptor: getProxyState");
410+
console.log(JSON.parse(state));
411+
```
412+
413+
#### Returns:
414+
415+
getProxyState will return a JSON string containing details about the proxy server and the ADB device status.
416+
417+
```json
418+
{
419+
"proxyServerStatus": {
420+
"isRegistered": true, // Indicates if the proxy exists in the internal cache
421+
"isStarted": true, // Indicates if the proxy server is currently running
422+
"deviceUDID": "R5CY127XBWB",
423+
"sessionId": "8e902882-ce19-44f6-90ca-975b167f94ca",
424+
"certificatePath": "/var/folders/.../8e902882-ce19-44f6-90ca-975b167f94ca",
425+
"port": 59046,
426+
"ip": "localhost"
427+
},
428+
"adbDeviceStatus": {
429+
"udid": "R5CY127XBWB",
430+
"activeAdbReverseTunnels": "UsbFfs tcp:56982 tcp:56982" // Current active reverse tunnels on the device
431+
}
432+
}
433+
```

src/plugin.ts

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { Application } from 'express';
44
import { CliArg, ISessionCapability, MockConfig, RecordConfig, RequestInfo, ReplayConfig, SniffConfig } from './types';
55
import { DefaultPluginArgs, IPluginArgs } from './interfaces';
66
import _ from 'lodash';
7-
import { configureWifiProxy, isRealDevice, getGlobalProxyValue } from './utils/adb';
7+
import { configureWifiProxy, isRealDevice, getGlobalProxyValue, getAdbReverseTunnels } from './utils/adb';
88
import { cleanUpProxyServer, sanitizeMockConfig, setupProxyServer } from './utils/proxy';
99
import proxyCache from './proxy-cache';
1010
import logger from './logger';
@@ -67,6 +67,10 @@ export class AppiumInterceptorPlugin extends BasePlugin {
6767
command: 'stopReplaying',
6868
params: { optional: ['id'] },
6969
},
70+
71+
'interceptor: getProxyState': {
72+
command: 'getProxyState',
73+
},
7074
};
7175

7276
constructor(name: string, cliArgs: CliArg) {
@@ -251,6 +255,39 @@ export class AppiumInterceptorPlugin extends BasePlugin {
251255
proxy.getRecordingManager().stopReplay(id);
252256
}
253257

258+
/**
259+
* Aggregates the current health and configuration state of the proxy system.
260+
* * This method performs a dual-layer diagnostic:
261+
* 1. Host Layer: Checks if the proxy instance exists in the cache and verifies its execution status.
262+
* 2. Transport Layer: Queries the physical device via ADB to list active reverse tunnels.
263+
* * It is primarily used to determine if a connectivity issue originates from the
264+
* Node.js server (Host) or the ADB bridge/USB connection (Device).
265+
*
266+
* @param next - The next middleware or handler in the execution chain (if applicable).
267+
* @param driver - The Appium driver instance containing the ADB controller and session ID.
268+
* @returns A Promise resolving to a JSON string representing the combined state of the proxy and ADB tunnels.
269+
*/
270+
async getProxyState(next: any, driver: any): Promise<string> {
271+
const adb = driver.adb;
272+
const udid = adb.curDeviceId;
273+
const adbReverseTunnels = await getAdbReverseTunnels(adb, udid);
274+
const proxy = proxyCache.get(driver.sessionId);
275+
const proxyServerStatus = {
276+
isRegistered: !!proxy,
277+
isStarted: proxy ? proxy.isStarted() : false,
278+
...proxy?.options,
279+
};
280+
const adbDeviceStatus = {
281+
udid: udid,
282+
activeAdbReverseTunnels: adbReverseTunnels,
283+
};
284+
const proxyState = {
285+
proxyServerStatus: proxyServerStatus,
286+
adbDeviceStatus: adbDeviceStatus,
287+
};
288+
return JSON.stringify(proxyState);
289+
}
290+
254291
async execute(next: any, driver: any, script: any, args: any) {
255292
return await this.executeMethod(next, driver, script, args);
256293
}

src/utils/adb.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,30 @@ export async function getGlobalProxyValue(
8383
}
8484
}
8585

86+
/**
87+
* Retrieves the list of all active ADB reverse port forwardings for a specific device.
88+
* * This method executes 'adb reverse --list' to identify which device ports are
89+
* currently bridged to the host machine. It is essential for diagnosing
90+
* connectivity between the mobile device and local proxy servers.
91+
*
92+
* @param adb - The ADB instance provided by the Appium driver.
93+
* @param udid - The Unique Device Identifier (UDID) of the target Android device.
94+
* @returns A Promise resolving to the raw string output of the 'adb reverse --list' command.
95+
* @throws {Error} If the command fails to execute or the device is unreachable.
96+
*/
97+
export async function getAdbReverseTunnels(
98+
adb: ADBInstance,
99+
udid: UDID
100+
): Promise<string> {
101+
try {
102+
return await adbExecWithDevice(adb, udid, [
103+
'reverse',
104+
'--list',
105+
]);
106+
} catch(error: any) {
107+
throw new Error(`Failed to list active reverse tunnels for device ${udid}: ${error.message}`);
108+
}
109+
}
86110

87111
export async function openUrl(adb: ADBInstance, udid: UDID, url: string) {
88112
await adbExecWithDevice(adb, udid, [

0 commit comments

Comments
 (0)