Skip to content

Commit

Permalink
feature(network): introducing Ktor interceptor (#272)
Browse files Browse the repository at this point in the history
* feat(network): add ktor network plugin (#252)

* feat: ktor interceptor

* address review comments

* ktlint

* address review comments

* Update build.gradle

---------

Co-authored-by: Prateek <[email protected]>

* additional fixes (#267)

* refactor & fixes

* refactor

* removed need to add base module as dependency

* code restructure

* refactor

* refactor

* move CacheDirectoryProvider to okhttp module

* PlutoInterceptor refactored

* refactor

* PlutoKtorInterceptor refactored

* access modifier fixed

* gradle fixes

* access modifier fixed

* mock setting in ktor interceptor

* refactor

* publish config fixes

* removed old custom interceptor logic

* data field cleanup

* init

* content type fix

* query param incorrect data fix

* sample code refactor

* fix(pluto): missing no-op methods added (#271)

* fix(pluto): missing no-op methods added

* pending fix

* added core no-op

* renaming

* merge conflict fix

* sample UI fixes

* review comments

---------

Co-authored-by: Aditya Kurkure <[email protected]>
  • Loading branch information
srtvprateek and epicadk authored Sep 13, 2023
1 parent fa247bd commit 13b6d29
Show file tree
Hide file tree
Showing 164 changed files with 1,181 additions and 753 deletions.
1 change: 0 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ allprojects {
repositories {
google()
mavenCentral()

// for testing Pluto staged repository
maven { url "https://s01.oss.sonatype.org/content/groups/staging/" }
}
Expand Down
1 change: 1 addition & 0 deletions dependencies.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@ ext {
composeCompileVersion = '1.4.7'
composeVersion = '1.4.0'
composeMaterial3Version = '1.0.1'

}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import androidx.annotation.MenuRes
import androidx.appcompat.view.menu.MenuBuilder
import androidx.appcompat.view.menu.MenuPopupHelper
import androidx.appcompat.widget.PopupMenu
import androidx.core.view.forEach
import com.pluto.plugin.R
import com.pluto.utilities.spannable.createSpan

Expand Down Expand Up @@ -37,11 +38,9 @@ private fun Context.applyFontToMenu(m: Menu) {
}

private fun Context.applyFontToMenuItem(mi: MenuItem) {
val subMenu = mi.subMenu
if (mi.hasSubMenu() && subMenu != null) {
for (i in 0 until subMenu.size()) {
applyFontToMenuItem(subMenu.getItem(i))
}

mi.subMenu?.forEach {
applyFontToMenuItem(it)
}

mi.title?.let { title ->
Expand Down
4 changes: 3 additions & 1 deletion pluto-plugins/bundle/lib-no-op/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@ android {

dependencies {
api project(path: ':pluto-plugins:plugins:exceptions:lib-no-op')
api project(path: ':pluto-plugins:plugins:network:lib-no-op')
api project(path: ':pluto-plugins:plugins:network:core:lib-no-op')
api project(path: ':pluto-plugins:plugins:network:interceptor-okhttp:lib-no-op')
api project(path: ':pluto-plugins:plugins:network:interceptor-ktor:lib-no-op')
api project(path: ':pluto-plugins:plugins:shared-preferences:lib-no-op')
api project(path: ':pluto-plugins:plugins:logger:lib-no-op')
api project(path: ':pluto-plugins:plugins:datastore:lib-no-op')
Expand Down
4 changes: 3 additions & 1 deletion pluto-plugins/bundle/lib/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@ android {

dependencies {
api project(path: ':pluto-plugins:plugins:exceptions:lib')
api project(path: ':pluto-plugins:plugins:network:lib')
api project(path: ':pluto-plugins:plugins:network:core:lib')
api project(path: ':pluto-plugins:plugins:network:interceptor-ktor:lib')
api project(path: ':pluto-plugins:plugins:network:interceptor-okhttp:lib')
api project(path: ':pluto-plugins:plugins:shared-preferences:lib')
api project(path: ':pluto-plugins:plugins:logger:lib')
api project(path: ':pluto-plugins:plugins:datastore:lib')
Expand Down
51 changes: 51 additions & 0 deletions pluto-plugins/plugins/network/core/lib-no-op/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
plugins {
id 'com.android.library'
id 'kotlin-android'
}

apply from: "$rootDir/scripts/build/utils.gradle"
apply from: "$rootDir/scripts/publish/module.gradle"

def verCode, verName, verBuild, verNameShort, verPublish
(verCode, verName, verBuild, verNameShort, verPublish) = genVersion()

ext {
PUBLISH_GROUP_ID = "com.plutolib.plugins"
PUBLISH_VERSION = verPublish
PUBLISH_ARTIFACT_ID = 'network-no-op'
}

android {
compileSdkVersion rootProject.compileSdkVersion
buildToolsVersion rootProject.buildToolsVersion

defaultConfig {
minSdkVersion rootProject.minSdkVersion
targetSdkVersion rootProject.targetSdkVersion
}

buildTypes {
release {
debuggable true
minifyEnabled false
shrinkResources false
}
}

compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}

kotlinOptions {
jvmTarget = JavaVersion.VERSION_1_8.toString()
}
namespace 'com.pluto.plugins.network'
lint {
abortOnError false
}

}

dependencies {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.pluto.plugins.network

data class RequestData(
val url: String,
val method: String,
val body: ProcessedBody?,
val headers: Map<String, String?>,
val sentTimestamp: Long
)

data class ResponseData(
val statusCode: Int,
val body: ProcessedBody?,
val headers: Map<String, String?>,
val sentTimestamp: Long,
val receiveTimestamp: Long,
val protocol: String = "",
val fromDiskCache: Boolean = false
)

data class ProcessedBody(
val body: CharSequence,
val contentType: String
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.pluto.plugins.network

import java.io.IOException

@SuppressWarnings("EmptyFunctionBlock", "UnusedPrivateMember")
class NetworkRecorder(private val request: RequestData) {

fun onError(e: IOException) {
}

fun onResponse(response: ResponseData) {
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.pluto.plugins.network

import android.content.Context

@SuppressWarnings("UnusedPrivateMember", "EmptyFunctionBlock")
object PlutoNetwork {

internal fun initialize(context: Context) {
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,9 @@ android {
viewBinding true
}


defaultConfig {
minSdkVersion rootProject.minSdkVersion
targetSdkVersion rootProject.targetSdkVersion

buildConfigField "String", "VERSION_NAME", "\"${verPublish}\""
}

Expand Down Expand Up @@ -62,11 +60,10 @@ dependencies {
implementation project(path: ':pluto-plugins:base:lib')
implementation "androidx.core:core-ktx:$androidXCoreVersion"

implementation "com.squareup.okhttp3:okhttp:$okhttpVersion"
implementation 'com.squareup.okio:okio:2.10.0'
implementation "io.ktor:ktor-client-core-jvm:2.3.2"

implementation "androidx.room:room-ktx:$roomsVersion"
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
ksp "androidx.room:room-compiler:$roomsVersion"

implementation "com.squareup.moshi:moshi:$moshiVersion"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.pluto.plugins.network

import android.content.Context

object PlutoNetwork {

var applicationContext: Context? = null
private set

internal fun initialize(context: Context) {
applicationContext = context.applicationContext
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package com.pluto.plugins.network.intercept

import com.pluto.plugins.network.internal.Status
import com.pluto.plugins.network.internal.interceptor.logic.mapCode2Message
import io.ktor.http.ContentType

object NetworkData {

data class Request(
val url: String,
val method: String,
val body: Body?,
val headers: Map<String, String?>,
val sentTimestamp: Long
) {
internal val isGzipped: Boolean
get() = headers["Content-Encoding"].equals("gzip", ignoreCase = true)
}

data class Response(
val statusCode: Int,
val body: Body?,
val headers: Map<String, String?>,
val sentTimestamp: Long,
val receiveTimestamp: Long,
val protocol: String = "",
val fromDiskCache: Boolean = false
) {
internal val status: Status
get() = Status(statusCode, mapCode2Message(statusCode))
val isSuccessful: Boolean
get() = statusCode in 200..299
internal val isGzipped: Boolean
get() = headers["Content-Encoding"].equals("gzip", ignoreCase = true)
}

data class Body(
val body: CharSequence,
val contentType: String
) {
private val contentTypeInternal: ContentType = ContentType.parse(contentType)
private val mediaType: String = contentTypeInternal.contentType
internal val mediaSubtype: String = contentTypeInternal.contentSubtype
internal val isBinary: Boolean = BINARY_MEDIA_TYPES.contains(mediaType)
val sizeInBytes: Long = body.length.toLong()
internal val mediaTypeFull: String = "$mediaType/$mediaSubtype"
}

internal val BINARY_MEDIA_TYPES = listOf("audio", "video", "image", "font")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package com.pluto.plugins.network.intercept

import com.pluto.plugins.network.internal.ApiCallData
import com.pluto.plugins.network.internal.MockConfig
import com.pluto.plugins.network.internal.interceptor.logic.NetworkCallsRepo
import com.pluto.plugins.network.internal.interceptor.logic.asExceptionData
import com.pluto.plugins.network.internal.mock.logic.MockSettingsRepo
import com.pluto.utilities.DebugLog
import java.io.IOException
import java.util.UUID

class NetworkInterceptor private constructor(private val request: NetworkData.Request, val option: Option) {
private val getRequestId: String = UUID.nameUUIDFromBytes("${System.currentTimeMillis()}::${request.url}".toByteArray()).toString()
private val apiCallData = ApiCallData(id = getRequestId, interceptorOption = option, request = request)
val requestUrlWithMockInfo: String = MockSettingsRepo.get(request.url, request.method)?.let {
apiCallData.mock = MockConfig(it)
NetworkCallsRepo.set(apiCallData)
it
} ?: run {
request.url
}

companion object {
fun intercept(request: NetworkData.Request, option: Option = Option()): NetworkInterceptor {
return NetworkInterceptor(request, option)
}
}

init {
NetworkCallsRepo.set(apiCallData)
}

fun onError(e: IOException) {
DebugLog.e("pluto.network", "error occurred", e)
apiCallData.exception = e.asExceptionData()
NetworkCallsRepo.set(apiCallData)
}

fun onResponse(response: NetworkData.Response) {
apiCallData.response = response
NetworkCallsRepo.set(apiCallData)
}

data class Option(
val name: String = "Custom",
val metadata: HashMap<String, String>? = null
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.pluto.plugins.network.internal

import com.pluto.plugins.network.intercept.NetworkData
import com.pluto.plugins.network.intercept.NetworkInterceptor
import com.pluto.plugins.network.internal.interceptor.logic.ExceptionData
import com.pluto.plugins.network.internal.share.getCurl
import com.pluto.utilities.list.ListItem

internal data class MockConfig(
val url: String,
)

internal data class Status(
val code: Int,
val message: String,
)

internal class ApiCallData(
val id: String,
val interceptorOption: NetworkInterceptor.Option,
val request: NetworkData.Request,
var response: NetworkData.Response? = null,
var exception: ExceptionData? = null,
var mock: MockConfig? = null,
val isCustomTrace: Boolean = false
) : ListItem() {
val curl: String
get() = request.getCurl()
val responseTime
get() = exception?.timeStamp ?: response?.receiveTimestamp

override fun isEqual(other: Any): Boolean {
if (other is ApiCallData) {
id == other.id && response == other.response && exception == other.exception
}
return false
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ package com.pluto.plugins.network.internal
import androidx.fragment.app.Fragment
import com.pluto.plugins.network.R

class NetworkFragment : Fragment(R.layout.pluto_network___fragment_network)
internal class NetworkFragment : Fragment(R.layout.pluto_network___fragment_network)
Loading

0 comments on commit 13b6d29

Please sign in to comment.