kittinunf / fuel

The easiest HTTP networking library for Kotlin/Android
https://fuel.gitbook.io/documentation/
MIT License
4.57k stars 430 forks source link

Error Response body #623

Closed rajeshdalsaniya closed 5 years ago

rajeshdalsaniya commented 5 years ago

With Previous Version I was successfully getting error response via response.data in code like this

Fuel.post(path, keyValues)
                        .responseJson { request, response, result ->
when (result) {
                                is Result.Failure -> {
                                    //TODO: Need attention to fix response error
                                   val errorMessage = parse(String(response.data))?.get("error")

                                }
                                is Result.Success -> {
                                    val myResult = result.value.obj()

                                }
}

But with latest version of Fuel it not working in android. I tried following code to get error code on Result Failure but it not working. Kindly guide me. Thanks

result.fold(success = { json ->
                                callback.onCompleted(ConstantData.APICallJSONResult(json.obj()))
                            }, failure = { error ->

                                Log.e("Failure", error.toString())
                                Log.e("Failure", error.localizedMessage)
                                Log.e("Failure", error.message)
                                Log.e("Failure", error.response.data.size.toString())

                            })

My json response is when Result Failure with status code 400 or 422

{
    "status": false,
    "error": "Something Wrong!"
}

Android Error coming when I try to access - result.component2()?.errorData? or error.errorData

Process: com.ggg.bbb, PID: 26876
    android.os.NetworkOnMainThreadException
        at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1460)
        at com.android.org.conscrypt.Platform.blockGuardOnNetwork(Platform.java:325)
        at com.android.org.conscrypt.OpenSSLSocketImpl$SSLInputStream.read(OpenSSLSocketImpl.java:724)
        at com.android.okhttp.okio.Okio$2.read(Okio.java:136)
        at com.android.okhttp.okio.AsyncTimeout$2.read(AsyncTimeout.java:211)
        at com.android.okhttp.okio.RealBufferedSource.request(RealBufferedSource.java:71)
        at com.android.okhttp.okio.RealBufferedSource.require(RealBufferedSource.java:64)
        at com.android.okhttp.okio.RealBufferedSource.readHexadecimalUnsignedLong(RealBufferedSource.java:270)
        at com.android.okhttp.internal.http.Http1xStream$ChunkedSource.readChunkSize(Http1xStream.java:454)
        at com.android.okhttp.internal.http.Http1xStream$ChunkedSource.read(Http1xStream.java:435)
        at com.android.okhttp.okio.RealBufferedSource$1.read(RealBufferedSource.java:371)
        at java.io.BufferedInputStream.read1(BufferedInputStream.java:286)
        at java.io.BufferedInputStream.read(BufferedInputStream.java:347)
        at java.io.FilterInputStream.read(FilterInputStream.java:133)
        at com.github.kittinunf.fuel.util.ProgressInputStream.read(ProgressInputStream.kt:46)
        at java.io.BufferedInputStream.read1(BufferedInputStream.java:286)
        at java.io.BufferedInputStream.read(BufferedInputStream.java:347)
        at java.io.FilterInputStream.read(FilterInputStream.java:107)
        at kotlin.io.ByteStreamsKt.copyTo(IOStreams.kt:110)
        at kotlin.io.ByteStreamsKt.copyTo$default(IOStreams.kt:103)
        at com.github.kittinunf.fuel.core.requests.DefaultBody.writeTo(DefaultBody.kt:87)
        at com.github.kittinunf.fuel.core.requests.DefaultBody.toByteArray(DefaultBody.kt:50)
        at com.github.kittinunf.fuel.core.Response.getData(Response.kt:32)
        at com.github.kittinunf.fuel.core.FuelError.getErrorData(FuelError.kt:72)
        at com.ggg.bbb.service.JsonParser$Companion$makeAPICall$2.invoke(JsonParser.kt:78)
        at com.ggg.bbb.service.JsonParser$Companion$makeAPICall$2.invoke(JsonParser.kt:23)
        at com.github.kittinunf.fuel.core.DeserializableKt$response$2.invoke(Deserializable.kt:106)
        at com.github.kittinunf.fuel.core.DeserializableKt$response$2.invoke(Unknown Source:6)
        at com.github.kittinunf.fuel.core.DeserializableKt$response$asyncRequest$2$1.invoke(Deserializable.kt:201)
        at com.github.kittinunf.fuel.core.DeserializableKt$response$asyncRequest$2$1.invoke(Unknown Source:0)
        at com.github.kittinunf.fuel.core.RequestExecutionOptionsKt$sam$java_lang_Runnable$0.run(Unknown Source:2)
        at android.os.Handler.handleCallback(Handler.java:808)
        at android.os.Handler.dispatchMessage(Handler.java:101)
        at android.os.Looper.loop(Looper.java:166)
        at android.app.ActivityThread.main(ActivityThread.java:7529)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:245)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:921)

Not I am using Laravel Lumen for API here is Code of Laravel lumen error response code

      $commonError = response()->json([
            'status' => false,
            'error' => 'Something Wrong!'
        ], 400);
SleeplessByte commented 5 years ago

Before, we would eagerly load the body response if it were an error. This consumed a lot of data on large error messages even if they were not used.

Now it only reads the error message once you ask for it (.read / .data / etc ).

Your exception is that you're doing this on the main thread. We can probably come up with a better solution for you here, but a temporary workaround would be to use a thread/coroutine/non main thread execution for reading the error message

rajeshdalsaniya commented 5 years ago

Before, we would eagerly load the body response if it were an error. This consumed a lot of data on large error messages even if they were not used.

Now it only reads the error message once you ask for it (.read / .data / etc ).

Your exception is that you're doing this on the main thread. We can probably come up with a better solution for you here, but a temporary workaround would be to use a thread/coroutine/non main thread execution for reading the error message

Thanks for your suggesion. I fixed the issue by making change in error handling code. as per below. I changed error handling as doAsync and Error message on uiThread (Note: I am using Anko Library for background task)


result.fold(success = { json ->
                                callback.onCompleted(ConstantData.APICallJSONResult(json.obj()))
                            }, failure = { error ->

                                Log.e("Failure", error.toString())
                                Log.e("Failure", error.response.statusCode.toString())
//                                Log.e("Failure", error.message)
                                doAsync {
                                    try {
                                        val errorMessage = parse(String(error.errorData))?.get("error")
                                        Log.e("Failure - T", errorMessage.toString())
                                        uiThread {
                                            CommonCalls.errorWithMessage(context, errorMessage.toString())
                                            callback.objectStatusUpdate(true)
                                        }
                                    } catch (e: Exception) {
                                        Log.e("Failure  - T", e.toString())
                                    } catch (e: FuelError) {
                                        Log.e("Failure  - T", e.toString())
                                    }
                                }