androidkotlinktorkotlin-multiplatform-mobile

How to get error message in api call response in ktor


I am learning Ktor. I want to print error value or exception. I have taken some piece of code from this post. I don't understand this post answer fully.

ApiResponse.kt

sealed class ApiResponse<out T : Any> {
    data class Success<out T : Any>(
        val data: T?
    ) : ApiResponse<T>()

    data class Error(
        val responseCode: Int = -1,
    ) : ApiResponse<Nothing>()

    fun handleResult(onSuccess: ((responseData: T?) -> Unit)?, onError: ((error: Error) -> Unit)?) {
        when (this) {
            is Success -> {
                onSuccess?.invoke(this.data)
            }
            is Error -> {
                onError?.invoke(this)
            }
        }
    }
}

@Serializable
data class ErrorResponse(
    var errorCode: Int = 1,
    val errorMessage: String = "Something went wrong"
)

KtorApi.kt

class KtorApi(private val httpClient: HttpClient) : NetworkRoute() {
    suspend fun getCat(): Response<CatResponse> {
        val response = httpClient.get {
            url("https://xyz/cat")
        }
        return apiCall(response)
    }
}

CatResponse.kt

@Serializable
data class CatResponse(
    val items: List<CatDetails>? = null
)

@Serializable
data class CatDetails(
    val id: String? = null,
    val name: String? = null,
)

ViewModel.kt

fun getCat() {
        viewModelScope.launch {
            KtorApi.getCat().handleResult({ data ->
                logE("Success on cat api response->>> $data")
            }) { error ->
                logE("Error on cat api ->>>> $error ")
            }
        }
   }

Here I have successfully get the data from the Success but I don't know how to get error or exception in error.

actual fun httpClient(config: HttpClientConfig<*>.() -> Unit) = HttpClient(OkHttp) {
    config(this)
    install(Logging) {
        logger = Logger.SIMPLE
        level = LogLevel.BODY
    }
    expectSuccess = false
    install(ContentNegotiation) {
        json(Json {
            prettyPrint = true
            ignoreUnknownKeys = true
            explicitNulls = false
        })
    }
}     

How can I pass my exception or error code, status, body in my ERROR data class? Anyone have an idea about that?


Solution

  • With kotlin suspend functions you need to catch errors using try/catch block:

    val apiResponse = try {
        ApiResponse.Success(KtorApi.getCat())
    } catch (e: ClientRequestException) {
        ApiResponse.Error(e.response.status)
    } catch (e: Exeption) {
        // some other error
        ApiResponse.Error()
    }