Fuel: FuelError content is empty if "Content-Type" header is not provided by a server

Created on 11 May 2020  路  5Comments  路  Source: kittinunf/fuel

Description

FuelError content is empty if Content-Type header is not provided by a server

To Reproduce

import com.github.kittinunf.fuel.core.Request
import com.github.kittinunf.fuel.core.FuelError
import com.github.kittinunf.result.Result


suspend fun <T> Request.requestWithAuthKey(
    clazz: Class<T>,
    permanentKey: String
): Unit {


    val (_, _, fuelResult) = appendHeader("AuthKey" to permanentKey)
        .authentication()
        .basic(userName, password)
        .awaitByteArrayResponseResult()


    when (fuelResult) {
        is Result.Failure -> logError()
        else -> { /* don't care */}
    }
} 

fun Result.Failure<FuelError>.logError()

    val bytes = error.response.data // empty if Content-Type header is missing, OK, if present
    val len = error.response.contentLength; // always OK, number of response's bytes
    val body = error.response.body().asString("text/plain") // empty if Content-Type header is missing, OK, if present
}

Expected behavior

Error content should be extractable no matter whether or not response contains Content-Type header.

Development Machine

_Complete the following information if applicable_

Windows 10, Kotlin 1.3, Android Studio 3.6.3

Smartphone or Emulator

Xiaomi Redmi Note 8 Pro or Genymotion

Additional context

Response headers

Date | Mon, 11 May 2020 15:44:59 GMT
-- | --
Server | Apache/2.4.35 (Win64) OpenSSL/1.1.1b PHP/7.2.19
Content-Length | bytes count here
Connection | close
Content-Type | application/json; charset=UTF-8 (or absent)

Response body

{  "testCyrillicValue": "邪斜胁谐写械卸"  }
bug

Most helpful comment

Content-Length 铆s a leaky abstraction. You can not use the Content-Length to determine the actual content-length, as _soon_ as you have a chunked, gzip or br or deflate Transfer-Encoding. That's how it's specced up in HTTP standards. Nothing we can do about that. The double downside is that Content-Encoding is often abused as Transfer-Encoding, meaning that usually Content-Encoding _also_ breaks the Content-Length because the server will _incorrectly_ report the "original" size, instead of the encoded size.

Data should _not_ be empty if there really is an error message. That is a 馃悰 bug. We would love to fix that 馃憤 馃槃

All 5 comments

If Content-Type is not given, we can not extract any content, because we don't know what the content is. We could expose the data stream as bytes or strings or whatever, and then you can use that directly (instead of the .as(xxx)) -- or perhaps allow this behaviour for _string_ content only, because that's generally safe.

@SleeplessByte , sorry if I've opened an issue for no reason.
The response could be octet/stream or whatever. And there's no any hint for library to guess what it should be. That's understood.

Which I cannot get is below:

my error.response.contentLength is 96 for example.
error.response.data is a byte array type. Why it's length is zero instead of 96?

If I try to get my response as stream it's also to no avail because of it's zero length.

So the more precise question is there any way I can get the same result with Fuel?


    val url = URL("http://localhost:8082")


    val connection = url.openConnection() as HttpURLConnection
    connection.apply {
        doOutput = true
        requestMethod = "POST"
    }

    if (connection.responseCode != 200) {
        connection.errorStream?.let {
            val bytes = it.readAllBytes() // not empty array is I'm expecting it with Fuel
            println (String(bytes, Charsets.UTF_8)) // I understand that it could be anything. If I get an exception here, that's OK.
        }
    }

If you agree with me that this is an issue, and there is not too much to rewrite, we can discuss about me creating a Pull Request to fix that. (In my opinion, byte array length I get from Fuel should match the content length. Otherwise it's a leaky abstraction)

Content-Length 铆s a leaky abstraction. You can not use the Content-Length to determine the actual content-length, as _soon_ as you have a chunked, gzip or br or deflate Transfer-Encoding. That's how it's specced up in HTTP standards. Nothing we can do about that. The double downside is that Content-Encoding is often abused as Transfer-Encoding, meaning that usually Content-Encoding _also_ breaks the Content-Length because the server will _incorrectly_ report the "original" size, instead of the encoded size.

Data should _not_ be empty if there really is an error message. That is a 馃悰 bug. We would love to fix that 馃憤 馃槃

Any news on resolution?
I'm worried that this problem occurs not only with errors but only with common response. If Content-Type is not provided the response is an empty byte array and so far I have not found a solution for this.

How can I do?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

fyi2 picture fyi2  路  3Comments

t-ae picture t-ae  路  5Comments

lfmingo picture lfmingo  路  4Comments

easazade picture easazade  路  6Comments

fnunezkanut picture fnunezkanut  路  6Comments