
jvmMain.retrofit.suspend.NetworkResponseSuspendCall.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of network-response-jvm Show documentation
Show all versions of network-response-jvm Show documentation
NetworkResponse multiplatform
The newest version!
package com.javiersc.resources.networkResponse.retrofit.suspend
import com.javiersc.resources.networkResponse.NetworkResponse
import com.javiersc.resources.networkResponse.isInternetAvailable
import com.javiersc.resources.networkResponse.ktor.emptyHeader
import com.javiersc.resources.networkResponse.retrofit.suspend.handlers.httpExceptionSuspendHandler
import com.javiersc.resources.networkResponse.retrofit.suspend.handlers.responseSuspendHandler
import com.javiersc.resources.networkResponse.utils.hasBody
import com.javiersc.resources.networkResponse.utils.printlnError
import com.javiersc.resources.networkResponse.utils.printlnWarning
import io.ktor.http.HttpStatusCode
import kotlinx.serialization.SerializationException
import okhttp3.Request
import okhttp3.ResponseBody
import okio.Timeout
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Converter
import retrofit2.HttpException
import retrofit2.Response
import java.io.EOFException
import java.io.InterruptedIOException
import java.net.ConnectException
import java.net.UnknownHostException
internal class NetworkResponseSuspendCall(
private val backingCall: Call,
private val errorConverter: Converter,
) : Call> {
override fun enqueue(callback: Callback>) = synchronized(this) {
backingCall.enqueue(
object : Callback {
override fun onResponse(call: Call, response: Response) {
response.responseSuspendHandler(
errorConverter,
this@NetworkResponseSuspendCall,
callback
)
}
override fun onFailure(call: Call, throwable: Throwable) {
when (throwable) {
is UnknownHostException, is ConnectException, is InterruptedIOException ->
onCommonConnectionExceptions(callback)
is EOFException -> onEOFException(callback)
is IllegalStateException -> onIllegalStateException(callback, throwable)
is HttpException -> onHttpException(callback, errorConverter, throwable)
is SerializationException ->
if (throwable.hasBody) onIllegalStateException(callback, throwable)
else onEOFException(callback)
else -> Response.success(NetworkResponse.UnknownError(throwable))
}
}
}
)
}
override fun isExecuted(): Boolean = synchronized(this) { backingCall.isExecuted }
override fun clone(): Call> =
NetworkResponseSuspendCall(backingCall.clone(), errorConverter)
override fun isCanceled(): Boolean = synchronized(this) { backingCall.isCanceled }
override fun cancel() = synchronized(this) { backingCall.cancel() }
override fun execute(): Response> =
throw UnsupportedOperationException("Suspend call does not support synchronous execution")
override fun request(): Request = backingCall.request()
override fun timeout(): Timeout = backingCall.timeout()
}
private fun Call>.onEOFException(callback: Callback>) {
printlnWarning(
"""
| # # # # # # # # # # # # # # WARNING # # # # # # # # # # # # # # # # # # #
| # Every 2XX response should have a body except 204/205, as the response #
| # was empty, the response is transformed to Success with code 204 and #
| # the headers are lost. The type should be Unit. #
| # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
""".trimMargin()
)
@Suppress("UNCHECKED_CAST")
try {
callback.onResponse(
this,
Response.success(NetworkResponse.Success(Unit as R, HttpStatusCode.NoContent, emptyHeader))
)
} catch (e: ClassCastException) {
printlnError(
"""
| # # # # # # # # # # # # # # ERROR # # # # # # # # # # # # # # # # # #
| # NetworkResponse should use Unit as Success type when body is null #
| # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
""".trimMargin()
)
callback.onResponse(this, Response.success(NetworkResponse.UnknownError(e)))
}
}
private fun Call>.onIllegalStateException(
callback: Callback>,
throwable: Throwable,
) {
printlnError(
"""
| # # # # # # # # # # # # # # ERROR # # # # # # # # # # # # # # #
| # Response body can't be serialized with the object provided #
| # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
""".trimMargin()
)
callback.onResponse(this, Response.success(NetworkResponse.UnknownError(throwable)))
}
private fun NetworkResponseSuspendCall.onCommonConnectionExceptions(
callback: Callback>,
) {
callback.onResponse(
this,
if (isInternetAvailable) Response.success(NetworkResponse.RemoteNotAvailable)
else Response.success(NetworkResponse.InternetNotAvailable)
)
}
private fun NetworkResponseSuspendCall.onHttpException(
callback: Callback>,
errorConverter: Converter,
exception: HttpException,
) = exception.httpExceptionSuspendHandler(errorConverter, this, callback)
© 2015 - 2025 Weber Informatics LLC | Privacy Policy