How can I add intercepter after decrypting the enc...
# chucker
s
How can I add intercepter after decrypting the encrypted response to show decrypted response in Android Chucker Plugin HttpClient for Ktor
Copy code
class AndroidNetworkGateway(
    private val debug: Boolean,
    private val interceptors: List<Interceptor>,
    private val networkInterceptor: List<Interceptor>,
    private val aesEncryptionManager: AesEncryptionManager,
) : INetworkGateway {

    override val client: HttpClient
        get() = HttpClient(OkHttp) {
            engine {
                config {
                    callTimeout(30, TimeUnit.SECONDS)
                    connectTimeout(30, TimeUnit.SECONDS)
                    readTimeout(30, TimeUnit.SECONDS)
                    writeTimeout(30, TimeUnit.SECONDS)
                }

                interceptors.forEach { addInterceptor(it) }
                networkInterceptor.forEach { addNetworkInterceptor(it) }
            }

            install(ContentNegotiation) {
                json(BaseApi.networkJsonParser)
            }

            install(Logging) {
                level = if (debug) LogLevel.ALL else LogLevel.NONE
            }

            install(ApiEncryption) {
                encryptionManager = aesEncryptionManager
            }
        }
}
ApiEncryption
Copy code
class ApiEncryption(private val aesEncryptionManager: AesEncryptionManager) {

    class Config {
        var encryptionManager: AesEncryptionManager? = null
    }

    companion object : HttpClientPlugin<Config, ApiEncryption> {
        override val key: AttributeKey<ApiEncryption> = AttributeKey(name = "ApiEncryption")

        override fun prepare(block: Config.() -> Unit): ApiEncryption {
            val config = Config().apply(block)
            val aesEncryptionManager = config.encryptionManager
                ?: throw IllegalArgumentException("AesEncryptionManager must be provided")
            return ApiEncryption(aesEncryptionManager)
        }

        @OptIn(ExperimentalStdlibApi::class, InternalAPI::class)
        override fun install(plugin: ApiEncryption, scope: HttpClient) {
            val aesEncryptionManager = plugin.aesEncryptionManager

            // Encrypt API Request
            scope.requestPipeline.intercept(phase = HttpRequestPipeline.Before) {
                if (this.context.body !is EmptyContent) {
                    val originalRequest = this.context.body.toString()
                    
                    val encryptedRequest =
                        aesEncryptionManager.encrypt(plainText = originalRequest)
                    proceedWith(subject = encryptedRequest)
                } else {
                    proceed()
                }
            }

            // Decrypt API Response
            scope.responsePipeline.intercept(phase = HttpResponsePipeline.Receive) { (info, body) ->
                try {
                    val encryptedResponse = this.context.response.content.readUTF8Line()

                    if (encryptedResponse?.isEncryptedResponse() == true) {
                        aesEncryptionManager.decrypt(
                            cipherText = encryptedResponse.data?.hexToByteArray()!!,
                            ivByteArray = encryptedResponse.iv?.hexToByteArray()!!,
                        ).also { decryptedResponse ->
                            proceedWith(
                                subject = HttpResponseContainer(
                                    expectedType = info,
                                    response = buildPacket {
                                        writeText(text = decryptedResponse)
                                    },
                                ),
                            )
                        }
                    } else {
                        proceedWith(
                            subject = HttpResponseContainer(
                                expectedType = info,
                                response = body,
                            ),
                        )
                    }
                } catch (exception: Exception) {
                    exception.printStackTrace()
                }
            }
        }
    }
}
As of now chucker intercepting a app encrypted request and server encrypted response in Chucker UI. I want to display decrypted response as well (will be available via ktor HttpResponsePipeline.After) Is there any plan to support this feature request? or Any way to do this at this moments
Edit I've created a another OkHttp intercepter and registered it before any other intercepter so other intercepter should receive a modified response as a input from OkHttp
Copy code
class ApiResponseInterceptor : Interceptor {
    @Throws(IOException::class)
    override fun intercept(chain: Interceptor.Chain): Response {
        val request: Request = chain.request()
        val response: Response = chain.proceed(request)
        if (response.code == 200) {
            val jsonObject = JSONObject()
            try {
                jsonObject.put("code", 200)
                jsonObject.put("status", "OK")
                jsonObject.put("message", "Successful")

                val contentType = response.body!!.contentType()
                val body: ResponseBody = ResponseBody.create(contentType, jsonObject.toString())
                return response.newBuilder().body(body).build()
            } catch (e: JSONException) {
                e.printStackTrace()
            }
        } else if (response.code == 403) {
        }
        return response
    }
}
But still Chucker showing original server response in UI
c
I don't really know what you're asking but interceptor order matters. so if you have an interceptor that does decreyption... then add chucker after that interceptor