icerockdev / moko-network

Network components with codegeneration of rest api for mobile (android & ios) Kotlin Multiplatform development
https://moko.icerock.dev
Apache License 2.0
154 stars 30 forks source link

Http-client request result handler before serialization #163

Open Tetraquark opened 3 years ago

Tetraquark commented 3 years ago

There is a situation when optional additional handling of a content of a server response in generated API classes by moko-network-generator plugin is needed. I need to pass some lambda or fun interface into constructor of *Impl classes. Then the lambda will be called after results receiving and before serialization process (here before 131 line): https://github.com/icerockdev/moko-network/blob/1b6bf98cb58752e1bc6f6df1d330826f8c3ef843/network-generator/src/main/resources/kotlin-ktor-client/api.mustache#L131

Use case: HTTP-server responds with errors using HTTP status 200 and there is some data of the error in the request body. As I understand it, at the moment there is no way to handle such thing using Ktor features because of io.ktor.client.call.DoubleReceiveException.

Alex009 commented 3 years ago

@Tetraquark hi! i think your case can be solved by something like Logger ktor feature. in this feature all content received (for logs) and later it passed to next pipeline step (just as copy as i know)

Alex009 commented 3 years ago

code that help:

scope.receivePipeline.intercept(HttpReceivePipeline.After) { response ->
    val charset = response.contentType()?.charset() ?: Charsets.UTF_8
    // Get body from content
    val body = response.content.readRemaining().readText(
        charset = charset
    )

    // Processing body
    val result = handleBody(body)
    if (result) {
        // Just proceed pipeline
        val byteChannel = ByteReadChannel(
            body.toByteArray(charset)
        )
        proceedWith(context.wrapWithContent(byteChannel).response)
    } else {
        throw Exception()
    }
}