Search code examples
ktorkotlinx.serialization

How to get status code of HttpCall with Ktor and kotlinx serialization


I am trying to figure out how to check the http status code of a http request with Ktor

I have a simple GET request like this with a HttpResponseObject that holds the data the server returns and any errors server side that I control

val response:HttpResponseObject<MyObject> = client.get<HttpResponseObject<MyObject>>(url)

Now what I need to also be able to check are is if there are unhandled exceptions or Authentication exceptions that get thrown by the server. In these cases nothing would be returned by the server and a status code of 500 or 401 error would be returned.

I see the documentation has you can get the full http response with something like this

val response:HttpResponse client.get(url)

but then how do lose my serialized data coming back and I couldnt find any examples on how to serialize it from the HttpResponse object.

Does anyone have any suggestions? is there a way to get the http status code from my first example?


Solution

  • What I ended up doing was using the HttpResponseValidator in the HttpClientConfig to catch the status codes then throw exceptions

    HttpResponseValidator{
    
                validateResponse { response: HttpResponse ->
                    val statusCode = response.status.value
                    when (statusCode) {
                        in 300..399 -> throw RedirectResponseException(response)
                        in 400..499 -> throw ClientRequestException(response)
                        in 500..599 -> throw ServerResponseException(response)
                    }
    
                    if (statusCode >= 600) {
                        throw ResponseException(response)
                    }
                }
            }
    

    By doing so I was then able to pass the error through my custom object back up to the UI

    private suspend fun getCurrentWeatherForUrl(url:String, callback: (HttpResponseObject<MyObject>?) -> Unit){
            var response:HttpResponseObject<MyObject>? = null
            response = try{
                client.get<HttpResponseObject<MyObject>>(url){
                    header("Authorization", "Bearer $authKey")
                }
            }catch (e:Exception){
                HttpResponseObject(null, e.toString())
            }
    
            callback(response)
        }
    

    Also you can use HttpResponse.receive() to get a serialized object AND the response data

    val response:HttpResponse = client.get(url)
    val myObject:MyObject = response.receive<MyObject>()