hey I am trying to learn ktor for my api request. I am reading Response validation in doc.
ApiResponse.kt
sealed class ApiResponse<out T : Any> {
data class Success<out T : Any>(
val data: T?
) : ApiResponse<T>()
data class Error(
val exception: Throwable? = null,
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"
)
I have this ApiResponse class in which, I want to handle api response through this post. As you see in the link, there is function called fetchResult
, inside that code is checking every time response.code()
and route according to domain specific Success or Error body. Is there any better way it will automatically route on specific domain rather than checking every time in ktor.
actual fun httpClient(config: HttpClientConfig<*>.() -> Unit) = HttpClient(OkHttp) {
config(this)
install(Logging) {
logger = Logger.SIMPLE
level = LogLevel.BODY
}
expectSuccess = false
HttpResponseValidator {
handleResponseExceptionWithRequest { exception, _ ->
val errorResponse: ErrorResponse
when (exception) {
is ResponseException -> {
errorResponse = exception.response.body()
errorResponse.errorCode = exception.response.status.value
}
}
}
}
}
KtorApi.kt
class KtorApi(private val httpClient: HttpClient) {
suspend fun getAbc(): Flow<KtorResponse> {
return httpClient.get {
url("abc")
}.body()
}
}
You can push through the
HttpResponsePipeline
an object of theApiResponse
type by intercepting the pipeline in theTransform
phase. In the interceptor, you can use aContentConverter
to deserialize a response body to an object of generic type (out T : Any
). Please note that this solution doesn't allow you to catch network exceptions. If you want to handle network or other exceptions you have to write a function that will return an object of theApiResponse
type as described in the article. Here is a complete example: