From 7f4676d63ef54435cb00ed5c7fc3576daf597167 Mon Sep 17 00:00:00 2001 From: Farshid Roohi Date: Fri, 9 Feb 2024 16:29:03 +0330 Subject: [PATCH 1/4] Add Host IP address in the overview and sharable --- .../internal/data/entity/HttpTransaction.kt | 3 +++ .../internal/data/room/ChuckerDatabase.kt | 2 +- .../chucker/internal/support/ResponseExt.kt | 17 +++++++++++++ .../internal/support/ResponseProcessor.kt | 1 + .../support/TransactionDetailsSharable.kt | 1 + .../TransactionOverviewFragment.kt | 1 + .../chucker_fragment_transaction_overview.xml | 25 +++++++++++++++++-- library/src/main/res/values/strings.xml | 1 + 8 files changed, 48 insertions(+), 3 deletions(-) create mode 100644 library/src/main/kotlin/com/chuckerteam/chucker/internal/support/ResponseExt.kt diff --git a/library/src/main/kotlin/com/chuckerteam/chucker/internal/data/entity/HttpTransaction.kt b/library/src/main/kotlin/com/chuckerteam/chucker/internal/data/entity/HttpTransaction.kt index 5d5921d4f..742a81c45 100644 --- a/library/src/main/kotlin/com/chuckerteam/chucker/internal/data/entity/HttpTransaction.kt +++ b/library/src/main/kotlin/com/chuckerteam/chucker/internal/data/entity/HttpTransaction.kt @@ -38,6 +38,7 @@ internal class HttpTransaction( @ColumnInfo(name = "protocol") var protocol: String?, @ColumnInfo(name = "method") var method: String?, @ColumnInfo(name = "url") var url: String?, + @ColumnInfo(name = "hostIp") var hostIp: String?, @ColumnInfo(name = "host") var host: String?, @ColumnInfo(name = "path") var path: String?, @ColumnInfo(name = "scheme") var scheme: String?, @@ -70,6 +71,7 @@ internal class HttpTransaction( protocol = null, method = null, url = null, + hostIp = null, host = null, path = null, scheme = null, @@ -317,6 +319,7 @@ internal class HttpTransaction( (protocol == other.protocol) && (method == other.method) && (url == other.url) && + (hostIp == other.hostIp) && (host == other.host) && (path == other.path) && (scheme == other.scheme) && diff --git a/library/src/main/kotlin/com/chuckerteam/chucker/internal/data/room/ChuckerDatabase.kt b/library/src/main/kotlin/com/chuckerteam/chucker/internal/data/room/ChuckerDatabase.kt index 43f5f29c7..0e0c8d735 100644 --- a/library/src/main/kotlin/com/chuckerteam/chucker/internal/data/room/ChuckerDatabase.kt +++ b/library/src/main/kotlin/com/chuckerteam/chucker/internal/data/room/ChuckerDatabase.kt @@ -6,7 +6,7 @@ import androidx.room.Room import androidx.room.RoomDatabase import com.chuckerteam.chucker.internal.data.entity.HttpTransaction -@Database(entities = [HttpTransaction::class], version = 9, exportSchema = false) +@Database(entities = [HttpTransaction::class], version = 10, exportSchema = false) internal abstract class ChuckerDatabase : RoomDatabase() { abstract fun transactionDao(): HttpTransactionDao diff --git a/library/src/main/kotlin/com/chuckerteam/chucker/internal/support/ResponseExt.kt b/library/src/main/kotlin/com/chuckerteam/chucker/internal/support/ResponseExt.kt new file mode 100644 index 000000000..f77c8378e --- /dev/null +++ b/library/src/main/kotlin/com/chuckerteam/chucker/internal/support/ResponseExt.kt @@ -0,0 +1,17 @@ +package com.chuckerteam.chucker.internal.support + +import okhttp3.Response +import java.util.regex.Matcher +import java.util.regex.Pattern + +private const val IP_REGEX = "(?:\\d{1,3}\\.){3}\\d{1,3}" + +public fun Response.getHostIp(): String? { + val body = body?.source()?.readUtf8() + val pattern: Pattern = Pattern.compile(IP_REGEX) + val matcher: Matcher? = body?.let { pattern.matcher(it) } + if (matcher?.find() == true) { + return matcher.group() + } + return null +} diff --git a/library/src/main/kotlin/com/chuckerteam/chucker/internal/support/ResponseProcessor.kt b/library/src/main/kotlin/com/chuckerteam/chucker/internal/support/ResponseProcessor.kt index 7a2c4cd9b..83fd989f0 100644 --- a/library/src/main/kotlin/com/chuckerteam/chucker/internal/support/ResponseProcessor.kt +++ b/library/src/main/kotlin/com/chuckerteam/chucker/internal/support/ResponseProcessor.kt @@ -43,6 +43,7 @@ internal class ResponseProcessor( requestDate = response.sentRequestAtMillis responseDate = response.receivedResponseAtMillis protocol = response.protocol.toString() + hostIp = response.getHostIp() responseCode = response.code responseMessage = response.message diff --git a/library/src/main/kotlin/com/chuckerteam/chucker/internal/support/TransactionDetailsSharable.kt b/library/src/main/kotlin/com/chuckerteam/chucker/internal/support/TransactionDetailsSharable.kt index 388b45272..158f9cbbd 100644 --- a/library/src/main/kotlin/com/chuckerteam/chucker/internal/support/TransactionDetailsSharable.kt +++ b/library/src/main/kotlin/com/chuckerteam/chucker/internal/support/TransactionDetailsSharable.kt @@ -13,6 +13,7 @@ internal class TransactionDetailsSharable( override fun toSharableContent(context: Context): Source = Buffer().apply { writeUtf8("${context.getString(R.string.chucker_url)}: ${transaction.getFormattedUrl(encodeUrls)}\n") + writeUtf8("${context.getString(R.string.chucker_host_ip)}: ${transaction.hostIp}\n") writeUtf8("${context.getString(R.string.chucker_method)}: ${transaction.method}\n") writeUtf8("${context.getString(R.string.chucker_protocol)}: ${transaction.protocol}\n") writeUtf8("${context.getString(R.string.chucker_status)}: ${transaction.status}\n") diff --git a/library/src/main/kotlin/com/chuckerteam/chucker/internal/ui/transaction/TransactionOverviewFragment.kt b/library/src/main/kotlin/com/chuckerteam/chucker/internal/ui/transaction/TransactionOverviewFragment.kt index ae961c2b9..f8619e11a 100644 --- a/library/src/main/kotlin/com/chuckerteam/chucker/internal/ui/transaction/TransactionOverviewFragment.kt +++ b/library/src/main/kotlin/com/chuckerteam/chucker/internal/ui/transaction/TransactionOverviewFragment.kt @@ -64,6 +64,7 @@ internal class TransactionOverviewFragment : Fragment() { ) { with(overviewBinding) { url.text = transaction?.getFormattedUrl(encodeUrl) + hostIp.text = transaction?.hostIp method.text = transaction?.method protocol.text = transaction?.protocol status.text = transaction?.status.toString() diff --git a/library/src/main/res/layout/chucker_fragment_transaction_overview.xml b/library/src/main/res/layout/chucker_fragment_transaction_overview.xml index b56440617..99c223c5e 100644 --- a/library/src/main/res/layout/chucker_fragment_transaction_overview.xml +++ b/library/src/main/res/layout/chucker_fragment_transaction_overview.xml @@ -38,6 +38,27 @@ app:layout_constraintTop_toTopOf="parent" tools:text="https://example.com/path/to/resource?here=might_be_really_long" /> + + + + + app:layout_constraintTop_toBottomOf="@id/host_ip" /> Request Response URL + Host IP Method Protocol Status From 99e5f45f8a0a9259c72b673b261222ade8ca85f7 Mon Sep 17 00:00:00 2001 From: Farshid Roohi Date: Fri, 9 Feb 2024 16:55:06 +0330 Subject: [PATCH 2/4] Add hostIp to the test utils and http transaction Dao test --- .../chucker/internal/data/entity/TransactionTestUtils.kt | 1 + .../chucker/internal/data/room/HttpTransactionDaoTest.kt | 1 + .../src/test/kotlin/com/chuckerteam/chucker/util/HarTestUtils.kt | 1 + .../com/chuckerteam/chucker/util/TestTransactionFactory.kt | 1 + 4 files changed, 4 insertions(+) diff --git a/library/src/test/kotlin/com/chuckerteam/chucker/internal/data/entity/TransactionTestUtils.kt b/library/src/test/kotlin/com/chuckerteam/chucker/internal/data/entity/TransactionTestUtils.kt index c4fe1a61a..eeae2eb80 100644 --- a/library/src/test/kotlin/com/chuckerteam/chucker/internal/data/entity/TransactionTestUtils.kt +++ b/library/src/test/kotlin/com/chuckerteam/chucker/internal/data/entity/TransactionTestUtils.kt @@ -23,6 +23,7 @@ internal fun HttpTransaction.withResponseData(): HttpTransaction = responseCode = 418 // I'm a teapot responseDate = 321L tookMs = 21L + hostIp = "192.168.1.1" responseTlsVersion = randomString() responseCipherSuite = randomString() responsePayloadSize = 0L diff --git a/library/src/test/kotlin/com/chuckerteam/chucker/internal/data/room/HttpTransactionDaoTest.kt b/library/src/test/kotlin/com/chuckerteam/chucker/internal/data/room/HttpTransactionDaoTest.kt index 662c4fd08..1e04ea705 100644 --- a/library/src/test/kotlin/com/chuckerteam/chucker/internal/data/room/HttpTransactionDaoTest.kt +++ b/library/src/test/kotlin/com/chuckerteam/chucker/internal/data/room/HttpTransactionDaoTest.kt @@ -60,6 +60,7 @@ internal class HttpTransactionDaoTest { assertThat(stringValue("responseHeaders")).isEqualTo(data.responseHeaders) assertThat(stringValue("method")).isEqualTo(data.method) assertThat(stringValue("url")).isEqualTo(data.url) + assertThat(stringValue("hostIp")).isEqualTo(data.hostIp) assertThat(stringValue("host")).isEqualTo(data.host) assertThat(stringValue("path")).isEqualTo(data.path) assertThat(stringValue("scheme")).isEqualTo(data.scheme) diff --git a/library/src/test/kotlin/com/chuckerteam/chucker/util/HarTestUtils.kt b/library/src/test/kotlin/com/chuckerteam/chucker/util/HarTestUtils.kt index d98f93606..af03984a5 100644 --- a/library/src/test/kotlin/com/chuckerteam/chucker/util/HarTestUtils.kt +++ b/library/src/test/kotlin/com/chuckerteam/chucker/util/HarTestUtils.kt @@ -29,6 +29,7 @@ internal object HarTestUtils { protocol = "HTTP", method = method, url = "http://localhost:80/getUsers", + hostIp = "192.168.1.1", host = "localhost", path = "/getUsers", scheme = "", diff --git a/library/src/test/kotlin/com/chuckerteam/chucker/util/TestTransactionFactory.kt b/library/src/test/kotlin/com/chuckerteam/chucker/util/TestTransactionFactory.kt index 6caa417cd..f417d0900 100644 --- a/library/src/test/kotlin/com/chuckerteam/chucker/util/TestTransactionFactory.kt +++ b/library/src/test/kotlin/com/chuckerteam/chucker/util/TestTransactionFactory.kt @@ -13,6 +13,7 @@ internal object TestTransactionFactory { protocol = "HTTP", method = method, url = "http://localhost:80/getUsers", + hostIp = "192.168.1.1", host = "localhost", path = "/getUsers", scheme = "", From d62681bc5944e9d3447c71d9869ed62833377531 Mon Sep 17 00:00:00 2001 From: Farshid Roohi Date: Fri, 9 Feb 2024 22:31:58 +0330 Subject: [PATCH 3/4] Write unit tests to get the host IP address extension function --- .../chucker/internal/support/ResponseExt.kt | 8 +++---- .../internal/support/ResponseProcessor.kt | 2 +- .../chucker/internal/data/har/ResponseTest.kt | 21 +++++++++++++++++++ 3 files changed, 26 insertions(+), 5 deletions(-) diff --git a/library/src/main/kotlin/com/chuckerteam/chucker/internal/support/ResponseExt.kt b/library/src/main/kotlin/com/chuckerteam/chucker/internal/support/ResponseExt.kt index f77c8378e..41d6471be 100644 --- a/library/src/main/kotlin/com/chuckerteam/chucker/internal/support/ResponseExt.kt +++ b/library/src/main/kotlin/com/chuckerteam/chucker/internal/support/ResponseExt.kt @@ -1,15 +1,15 @@ package com.chuckerteam.chucker.internal.support -import okhttp3.Response +import okio.BufferedSource import java.util.regex.Matcher import java.util.regex.Pattern private const val IP_REGEX = "(?:\\d{1,3}\\.){3}\\d{1,3}" -public fun Response.getHostIp(): String? { - val body = body?.source()?.readUtf8() +public fun BufferedSource.getHostIp(): String? { + val body = readUtf8() val pattern: Pattern = Pattern.compile(IP_REGEX) - val matcher: Matcher? = body?.let { pattern.matcher(it) } + val matcher: Matcher? = body.let { pattern.matcher(it) } if (matcher?.find() == true) { return matcher.group() } diff --git a/library/src/main/kotlin/com/chuckerteam/chucker/internal/support/ResponseProcessor.kt b/library/src/main/kotlin/com/chuckerteam/chucker/internal/support/ResponseProcessor.kt index 83fd989f0..72fead15f 100644 --- a/library/src/main/kotlin/com/chuckerteam/chucker/internal/support/ResponseProcessor.kt +++ b/library/src/main/kotlin/com/chuckerteam/chucker/internal/support/ResponseProcessor.kt @@ -43,7 +43,7 @@ internal class ResponseProcessor( requestDate = response.sentRequestAtMillis responseDate = response.receivedResponseAtMillis protocol = response.protocol.toString() - hostIp = response.getHostIp() + hostIp = response.body?.source()?.getHostIp() responseCode = response.code responseMessage = response.message diff --git a/library/src/test/kotlin/com/chuckerteam/chucker/internal/data/har/ResponseTest.kt b/library/src/test/kotlin/com/chuckerteam/chucker/internal/data/har/ResponseTest.kt index 003b9111c..8476c3ea2 100644 --- a/library/src/test/kotlin/com/chuckerteam/chucker/internal/data/har/ResponseTest.kt +++ b/library/src/test/kotlin/com/chuckerteam/chucker/internal/data/har/ResponseTest.kt @@ -1,8 +1,10 @@ package com.chuckerteam.chucker.internal.data.har import com.chuckerteam.chucker.internal.data.har.log.entry.response.Content +import com.chuckerteam.chucker.internal.support.getHostIp import com.chuckerteam.chucker.util.HarTestUtils import com.google.common.truth.Truth.assertThat +import okhttp3.mockwebserver.MockResponse import org.junit.Test internal class ResponseTest { @@ -48,4 +50,23 @@ internal class ResponseTest { assertThat(response?.bodySize).isEqualTo(1000) } + + @Test + fun `host ip address from response successfully`() { + val body = + "{\"args\": {},\"origin\": \"192.168.1.1\", \"url\": \"https://httpbin.org/get\"}" + val response = MockResponse().setBody(body).setResponseCode(200) + val buffer = response.getBody() + val hostIp = buffer?.getHostIp() + assertThat(hostIp).isEqualTo("192.168.1.1") + } + @Test + fun `host ip address from response doesn't exist`() { + val body = + "{\"args\": {}, \"url\": \"https://httpbin.org/get\"}" + val response = MockResponse().setBody(body).setResponseCode(200) + val buffer = response.getBody() + val hostIp = buffer?.getHostIp() + assertThat(hostIp).isEqualTo(null) + } } From 0450ef69e4d2fe9efe5ce91e6954585bb2cb7b9b Mon Sep 17 00:00:00 2001 From: Farshid Roohi Date: Fri, 9 Feb 2024 22:32:12 +0330 Subject: [PATCH 4/4] Write unit tests to get the host IP address extension function --- .../com/chuckerteam/chucker/internal/data/har/ResponseTest.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/library/src/test/kotlin/com/chuckerteam/chucker/internal/data/har/ResponseTest.kt b/library/src/test/kotlin/com/chuckerteam/chucker/internal/data/har/ResponseTest.kt index 8476c3ea2..b824c70b5 100644 --- a/library/src/test/kotlin/com/chuckerteam/chucker/internal/data/har/ResponseTest.kt +++ b/library/src/test/kotlin/com/chuckerteam/chucker/internal/data/har/ResponseTest.kt @@ -60,6 +60,7 @@ internal class ResponseTest { val hostIp = buffer?.getHostIp() assertThat(hostIp).isEqualTo("192.168.1.1") } + @Test fun `host ip address from response doesn't exist`() { val body =