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 5d5921d4..742a81c4 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 43f5f29c..0e0c8d73 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 00000000..41d6471b --- /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 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 BufferedSource.getHostIp(): String? { + val body = 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 7a2c4cd9..72fead15 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.body?.source()?.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 388b4527..158f9cbb 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 ae961c2b..f8619e11 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 b5644061..99c223c5 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 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 c4fe1a61..eeae2eb8 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/har/ResponseTest.kt b/library/src/test/kotlin/com/chuckerteam/chucker/internal/data/har/ResponseTest.kt index 003b9111..b824c70b 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,24 @@ 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) + } } 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 662c4fd0..1e04ea70 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 d98f9360..af03984a 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 6caa417c..f417d090 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 = "",