kotlin-multiplatformktorktor-client

Ktor won't get response body from response.body()


This is my problem (Logcat):

I  HttpClient: REQUEST: http://...
I  METHOD: HttpMethod(value=POST)
I  COMMON HEADERS
I  -> Accept: application/json
I  -> Accept-Charset: UTF-8
I  -> Content-Type: application/json 
I  CONTENT HEADERS
I  -> Content-Length: 0
I  BODY Content-Type: null
I  BODY START
I  
I  BODY END
I  well well wellnull
I  HttpClient: RESPONSE: 401 Unauthorized
I  METHOD: HttpMethod(value=POST)
I  FROM: http://...
I  COMMON HEADERS
I  -> cache-control: no-cache, private
I  -> connection: keep-alive
I  -> content-type: application/json
I  -> date: Wed, 14 Aug 2024 03:43:27 GMT
I  -> server: nginx/1.18.0 (Ubuntu)
I  -> transfer-encoding: chunked
I  -> x-android-received-...: 1723607006217
I  -> x-android-response-source: NETWORK 401
I  -> x-android-selected-protocol: http/1.1
I  -> x-android-sent-...: 1723607006056
I  BODY Content-Type: application/json
I  BODY START
I  {"message":"User already logged in!","token":"......"}
I  BODY END

This is my first time using Ktor because i need to use it. Idk why Ktor getting response body from request instead of response, the first one is null (black space between BODY START and BODY END) and the 2nd one is not null with message "User already logged in!", and i need to get the 2nd one.

Just like the screenshot, I've tried to check it with println and it return null ("well well wellnull"). I don't know how to get the second one that i marked green.

This is my client:

val ktorHttpClient = HttpClient{
    install(ContentNegotiation){
        json(Json {
            prettyPrint = true
            ignoreUnknownKeys = true
        })
    }

    install(Logging){
        logger = Logger.SIMPLE
        level = LogLevel.ALL
    }

    install(HttpTimeout){
        requestTimeoutMillis = 15000
    }
}

And this is my repository:

suspend fun userlogin(theurl: String, userrequest: LoginRequest): LoginResponse{
        val response = try {
            ktorHttpClient.post("${theurl}/login"){
                contentType(ContentType.Application.Json)
                parameter("username", userrequest.username)
                parameter("password", userrequest.password)
            }
        } catch (e: UnresolvedAddressException){
            //ktorHttpClient.close()
            return LoginResponse(message = e.message)
        } catch (e: SerializationException) {
            //ktorHttpClient.close()
            return LoginResponse(message = e.message)
        }

        //ktorHttpClient.close()
        return when(response.status.value){
            in 200..299 ->{
                response.body()
            }
            else -> response.body()
        }
    }

EDIT: Okay so i already got what happened. The "response.body()" does not return the body that contains "message" and "token" but instead the URL and status code. I need to get that message and token and return it as LoginResponse (serializable data class)


Solution

  • Okay, so turns out im getting the wrong data. I thought response.body() is the JSON string i got, turns out it was not and it will always return null bcuz response.body() only contains url and status code.

    So i got the string json from response.call.response.bodyAsText(). And then i convert it or decode it into data class using:

    val loginJson: LoginResponse = Json.decodeFromString( respon.call.response.bodyAsText())
    

    Then i return "loginJson".