Ktor: Apache HTTP Client does not send Content-Length header if body is empty content

Created on 10 Sep 2019  ยท  6Comments  ยท  Source: ktorio/ktor

Ktor Version and Engine Used (client or server and name)
io.ktor:ktor-client-core:1.2.4
io.ktor:ktor-client-core-jvm:1.2.4
io.ktor:ktor-client-apache:1.2.4

Describe the bug
Apache HTTP Client does not send Content-Length header if body is empty content.
CIO send the header correctly.

To Reproduce
Steps to reproduce the behavior:

  1. Write the following
val apacheClient = HttpClient(Apache)
apacheClient.put<HttpResponseData>("http://example.com/") 
apacheClient.post<HttpResponseData>("http://example.com/")
apacheClient.patch<HttpResponseData>("http://example.com/")
  1. Run on jvm
  2. The sent header does not contain Content-Length
{
  "accept-charset": "UTF-8",
  "accept": "*/*",
  "user-agent": "Ktor client",
  "host": "example.com",
  "connection": "Keep-Alive" 
}

Some endpoints that do not require body return 411 Length Required.

Expected behavior
Content-Length: 0 Should be sent.

Apache seems not to send Content-Length if entity is null.
Following code sent the header correctly.

apacheClient.put<HttpResponseData>("http://example.com/"){
    body = ""
}

The relevant part of the code in ktor:
https://github.com/ktorio/ktor/blob/f3858b2bd95dcb35aa7755451403e7cab1dd678c/ktor-client/ktor-client-apache/jvm/src/io/ktor/client/engine/apache/ApacheRequestProducer.kt#L122-L155

and org.apache.http.client.methods.RequestBuilder 's build() method.

bug

All 6 comments

The question is: how can a post request with no content-length, no transfer-encoding and keep-alive connection work at allโ“

No. It's a client issue, not a server issue.
I tried to send a empty put request to a third-party api server.

val apacheClient = HttpClient(Apache)
apacheClient.put<HttpResponseData>("http://example.com/") 

However, the server returns 411 Length Required.
The cause is Ktor client with Apache engine didn't send content-length header.

content-length or transfer-encoding headers should be present.

RFC 7230, section 3.3.2: Content-Length

For example, a Content-Length header
field is normally sent in a POST request even when the value is 0
(indicating an empty payload body).

hi guys, i've encountered this bug in one of our production systems. we temporarily added the solution (hack?) of simply setting the body to "". in order to fix it properly i've created a PR which should do the job: https://github.com/ktorio/ktor/pull/1644

any feedback on this would be highly appreciated.

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

Had the same problem. Have solved it with the following workaround:

val client = HttpClient(Apache) {
    engine {
        customizeClient {
            setDefaultHeaders(mutableListOf(BasicHeader("Content-Length", "0")))
        }
    }
}

client.post<MyResponse>(ENDPOINT_URL) { ... }

One should use this configuration only for requests where you invoke PUT/POST methods with empty body.
It isn't the perfect solution, but if one can't use another engine for the client it will help.

The fix is merged in 1.3.0

Was this page helpful?
0 / 5 - 0 ratings