Skip to content

Android app cannot connect to Mockttp server - "socket hang up" error #167

@PhamH1eu

Description

@PhamH1eu

Environment

  • HTTP Toolkit Server version: 1.24.1
  • Android device: Emulator (emulator-5554)
  • Setup: Python script automating HTTP Toolkit integration (simulating UI flow)

Problem

Android app (tech.httptoolkit.android.v1) installs successfully but cannot connect to Mockttp server. Server logs show:
Mock session started, http on port 8000, webrtc enabled
...
Failed to handle request: socket hang up
Failed to handle request: socket hang up

Httptoolkit app on mobile device show "We couldn't connect to HTTP Toolkit. Is it running, and connected to the same network as this device?"

Flow we're using (simulating UI behavior)

We're following the exact same flow as the HTTP Toolkit UI website's worked version

1. Start Mockttp session

POST http://127.0.0.1:45456/start
Content-Type: application/json
Origin: https://app.httptoolkit.tech

{
"plugins": {
"http": {
"options": {
"cors": false,
"suggestChanges": false,
"http2": "fallback",
"https": {"tlsPassthrough": []},
"socks": true
}
},
"webrtc": {}
}
}
Response:
{
"id": "6bffc757-67ca-4d43-81c0-8a84b2f34440",
"pluginData": {
"http": {
"port": 8000,
"mockRoot": "https://localhost:8000"
},
"webrtc": {}
}
}

2. Set upstream proxy rules (simulating rules-store.ts reaction)

POST http://127.0.0.1:45456/session/{session_id}/
Content-Type: application/json
Origin: https://app.httptoolkit.tech

{
"query": "mutation SetRules($newRules: [MockRule!]!) { endpoints: setRules(input: $newRules) { id explanation } }",
"variables": {
"newRules": [{
"id": "default-wildcard",
"matchers": [{"type": "wildcard", "uiType": "default-wildcard"}],
"steps": [{
"type": "passthrough",
"proxyConfig": {
"proxyUrl": "http://gw.dataimpulse.com:823",
"noProxy": [],
"additionalTrustedCAs": []
},
"lookupOptions": {
"servers": ["127.0.0.1:8000"]
},
"simulateConnectionErrors": true,
"ignoreHostCertificateErrors": ["localhost"],
"extraCACertificates": [],
"clientCertificateHostMap": {},
"hasBeforeRequestCallback": false,
"hasBeforeResponseCallback": false
}]
}]
}
}
Also set WebSocket rules with same proxyConfig and lookupOptions.

3. Activate Android interceptor (simulating interceptor-store.ts)

POST http://127.0.0.1:45457/interceptors/android-adb/activate/8000
Content-Type: application/json
Origin: https://app.httptoolkit.tech

{
"deviceId": "emulator-5554"
}
Server behavior:

  • ✅ APK installs successfully
  • ✅ Certificate injection works
  • ✅ Chrome flags set successfully
  • ✅ ADB reverse tunnel created: adb reverse tcp:8000 tcp:8000
  • ✅ Android app launched with intent: tech.httptoolkit.android.ACTIVATE
  • ✅ Intent data includes correct port in setupParams:
    {
    "addresses": [...],
    "port": 8000,
    "localTunnelPort": 8000,
    "enableSocks": false,
    "certFingerprint": "..."
    }

    What happens

  1. ✅ Session created on port 8000
  2. ✅ Upstream proxy configured for session
  3. ✅ Android interceptor activated with port 8000
  4. ✅ ADB reverse tunnel exists: tcp:8000 tcp:8000 (verified via adb reverse --list)
  5. Connection fails: "socket hang up" error

Verification

  • Port consistency: All operations use port 8000 from /start response
  • ADB reverse tunnel: tcp:8000 tcp:8000 exists and verified
  • Session exists: Server log shows "Mock session started, http on port 8000"
  • Intent data: Android app receives correct port in setupParams.port and setupParams.localTunnelPort
  • Flow matches UI: Same sequence as web UI (start session → set rules → activate)

Expected behavior

Android app should successfully connect to 127.0.0.1:8000 via ADB reverse tunnel and establish VPN connection.

Actual behavior

Android app attempts to connect but gets "socket hang up" error. Connection fails before VPN service can start.

Additional context

  • This flow exactly matches the UI behavior:
    • proxy-store.ts: Start session via PluggableAdmin.AdminClient.start()
    • rules-store.ts: Auto-sync rules via reaction when proxyConfig changes
    • interceptor-store.ts: activateInterceptor() with proxyPort
  • We're using the same API endpoints and formats as the web UI
  • The issue occurs even when all ports match correctly
  • Manual adb reverse tcp:8000 tcp:8000 doesn't help (tunnel already exists)

Questions

  1. Are there any additional requirements for the session or rules configuration?
  2. Could this be related to the session being created via /start API vs. the UI's PluggableAdmin client (WebSocket connection)?
  3. Does the Android app need the session to be "active" or have specific rules already set before it can connect?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions