ktor icon indicating copy to clipboard operation
ktor copied to clipboard

404 doesn't throw an exception

Open kuuuurt opened this issue 6 years ago • 6 comments

Ktor 1.2.4 - Client

  • OkHttp
  • JSON
  • Serialization

Describe the bug It seems that it doesn't catch 404's in an error

To Reproduce

  1. Here's my code:
val httpClientEngine by lazy {
    OkHttp.create {
        if (BuildConfig.DEBUG) {
            addInterceptor(HttpLoggingInterceptor().apply {
                level = HttpLoggingInterceptor.Level.BODY
            })
        }
    }
}

private val httpClient = HttpClient(httpClientEngine) {
    install(JsonFeature) {
        serializer = KotlinxSerializer(Json.nonstrict)
    }
}

suspend fun myFunction(data: Any) = httpCall {
    httpClient.call("my_invalid_url") {
        contentType(ContentType.Application.Json
        method = HttpMethod.Post
        body = MyRequest(data)
    }
}

And here's the httpCall wrapper:

suspend inline fun <T> httpCall(call: () -> T) = try {
    call()
} catch (exception: ClientRequestException) {
    val errorResponse = exception.response.receive<MyErrorResponse>()
    var message = errorResponse.message

    throw Exception(message)
}

However, 404's just pass through this.

Here's the response from the server:

<-- 404 Not Found http://127.0.0.1/my_invalid_url (420ms)        
Server: nginx/1.15.12                                               
Date: Wed, 13 Nov 2019 07:18:25 GMT                                 
Content-Type: text/html; charset=utf-8                              
Content-Length: 152                                                 
Connection: keep-alive                                              
X-Powered-By: Express                                               
Access-Control-Allow-Origin: *                                      
Content-Security-Policy: default-src 'none'                         
X-Content-Type-Options: nosniff                                     
<!DOCTYPE html>                                                     
<html lang="en">                                                    
<head>                                                              
<meta charset="utf-8">                                              
<title>Error</title>                                                
</head>                                                             
<body>                                                              
<pre>Cannot POST /my_invalid_url</pre>                                
</body>                                                             
</html>                                                             
<-- END HTTP (152-byte body)                                        

I'm thinking I should need to register an XML serializer? But I can't find anything in the documentation. If I'm missing something, please do point me in the right direction.

Many thanks!

Expected behavior It should catch 404's as an error

kuuuurt avatar Nov 13 '19 07:11 kuuuurt

Hi @kuuuurt, thanks for the report. Yep, it should be the exception here. Btw there is no XML feature out of the box.

Probably we can have an integration with https://github.com/pdvrieze/xmlutil for XML

e5l avatar Nov 18 '19 14:11 e5l

Seems like it's just the call making errors pass through. I think there's no need for an XML (at least in my case)

kuuuurt avatar Nov 18 '19 15:11 kuuuurt

What type of content do you receive from the call? The client validates a call only in call receiving.

e5l avatar Dec 02 '19 12:12 e5l

Some JSON data which I deserialize with Kotlinx serialization. This specific case happened when I had a wrong URL and I'm just getting this

<!DOCTYPE html>                                                     
<html lang="en">                                                    
<head>                                                              
<meta charset="utf-8">                                              
<title>Error</title>                                                
</head>                                                             
<body>                                                              
<pre>Cannot POST /my_invalid_url</pre>                                
</body>                                                             
</html>   

instead of the JSON string but when I have the correct URL and receive this:

{
    code: 200
    data: { ... }
}

It works as expected.

I used post<Unit> instead of call and it doesn't bypass the errors anymore.

kuuuurt avatar Dec 04 '19 07:12 kuuuurt

Please check the following ticket on YouTrack for follow-ups to this issue. GitHub issues will be closed in the coming weeks.

oleg-larshin avatar Aug 10 '20 15:08 oleg-larshin

Ticket is a bit old, but it seems to me like the HttpClient configuration misses expectSuccess = true in order for the call to fail in case of a non-20X HTTP status. See https://ktor.io/docs/client-response-validation.html#default

mrlem avatar Dec 08 '24 13:12 mrlem