Skip to content

Commit f6cc97c

Browse files
committed
Fallback to amiusing.htk/certificate if android.htk/config is missing
This can easily happen if you set up Android interception in HTTP Toolkit, restart the desktop app, and then reconnect from the Android app. Doing so re-queries the android config, which is no longer set up (as the desktop isn't expecting a client). Easily fixable by falling back to the basic cert info (potentially losing extra config data, if we do include some here later).
1 parent 1e12697 commit f6cc97c

File tree

1 file changed

+21
-10
lines changed

1 file changed

+21
-10
lines changed

app/src/main/java/tech/httptoolkit/android/ProxySetup.kt

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ import java.util.concurrent.TimeUnit
2525

2626
private val TAG = formatTag("tech.httptoolkit.android.ProxySetup")
2727

28+
class ResponseException(message: String) : ConnectException(message)
29+
2830
// Takes an android.httptoolkit.tech/connect URI, extracts & parses the connection config
2931
// within, into a format ready for testing and then usage.
3032
fun parseConnectUri(uri: Uri): ProxyInfo {
@@ -80,18 +82,16 @@ private suspend fun testProxyAddress(
8082

8183
Log.i(TAG, "Testing proxy $address:$port")
8284

83-
val request = Request.Builder()
84-
.url("http://android.httptoolkit.tech/config")
85-
.build()
86-
8785
try {
88-
val configString = httpClient.newCall(request).execute().use { response ->
89-
if (response.code != 200) {
90-
throw ConnectException("Proxy responded with non-200: ${response.code}")
91-
}
92-
response.body!!.string()
86+
val config = try {
87+
val configString = request(httpClient, "http://android.httptoolkit.tech/config")
88+
Klaxon().parse<ReceivedProxyConfig>(configString)!!
89+
} catch (e: ResponseException) {
90+
// If we connected but the response was bad, maybe we're reconnecting to an app
91+
// that isn't explicitly expecting an Android client. Retry requesting just the cert.
92+
val certString = request(httpClient, "http://amiusing.httptoolkit.tech/certificate")
93+
ReceivedProxyConfig(certString)
9394
}
94-
val config = Klaxon().parse<ReceivedProxyConfig>(configString)!!
9595

9696
val foundCert = certFactory.generateCertificate(
9797
ByteArrayInputStream(config.certificate.toByteArray(Charsets.UTF_8))
@@ -118,6 +118,17 @@ private suspend fun testProxyAddress(
118118
}
119119
}
120120

121+
suspend fun request(httpClient: OkHttpClient, url: String): String {
122+
return withContext(Dispatchers.IO) {
123+
httpClient.newCall(Request.Builder().url(url).build()).execute().use { response ->
124+
if (response.code != 200) {
125+
throw ResponseException("Proxy responded with non-200: ${response.code}")
126+
}
127+
response.body!!.string()
128+
}
129+
}
130+
}
131+
121132
fun getCertificateFingerprint(cert: X509Certificate): String {
122133
val md = MessageDigest.getInstance("SHA-256")
123134
md.update(cert.publicKey.encoded)

0 commit comments

Comments
 (0)