# Java 17: Missing content-length header on a multipartfile request

**URL:** <https://softwaremill.community/t/java-17-missing-content-length-header-on-a-multipartfile-request/206>\
**Category:** sttp client\
**Created:** [May 17, 2023, 2:55pm UTC](https://softwaremill.community/t/java-17-missing-content-length-header-on-a-multipartfile-request/206 "2023-05-17T14:55:54Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![leszek](https://avatars.discourse-cdn.com/v4/letter/l/82dd89/32.png) [@leszek](https://softwaremill.community/u/leszek)\
**Post date:** [May 17, 2023, 2:55pm UTC](https://softwaremill.community/t/java-17-missing-content-length-header-on-a-multipartfile-request/206/1 "2023-05-17T14:55:54Z")

</div>

Hello,  
I am using STTP 3.8.15 with ZIO backend, Java 17 ZULU.

So, given this code

```auto
  override def uploadFile(
    connection: Connection,
    path: String,
    file: File,
    overwrite: Boolean
  ): IO[BusinessError, Unit] =
    sendRequest(s"File upload to $path", AcceptedContent.any)( // custom function
      basicDBRequest
        .post(uri"https://something/put")
        .auth.bearer(connection.token.value)
        .multipartBody(
          multipart("path", path),
          multipart("overwrite", overwrite),
          multipartFile("contents", file)
        ),
      noOpCallHandler[String, String]
    ).mapErrorCause(fromError)
      .ignore

```

The server returns 400 with `Content-Length header must be provided. This is required to avoid uploading partial data.`.

Using requestbin, I see that indeed there is no `content-length` header sent:

```auto
transfer-encoding: chunked
accept: */*
accept-encoding: gzip, deflate
content-type: multipart/form-data; boundary=8f9cab0d-2f53-4d2b-b8b1-1414d7b7dbb2

```

I’ve tried to set one, but frankly, however I try to calculate and set it, I always get another error: `Too many bytes in request body. Expected: 37131145, got: 37131695`

1. Shouldn’t the content-length header be sent automatically in this case? The length of the body is known as it’s an existing file.
2. If not, how can I have calculate the body of such multipart request or ask STTP to define Content-Length?

I noticed, that with Java 11, the `content-length` header is sent instead of `Transfer-Encoding: chunked`. Am I able to configure STTP (and underlaying classes) to use `content-length` header?

Thank you!

BTW the `Slf4jLoggingBackend` does not log `POST` requests, I see only GET ones. I have configured it this way for my tests

```auto
HttpClientZioBackend.layer().map(env =>
  ZEnvironment(Slf4jLoggingBackend(
    delegate = env.get[SttpClient],
    beforeCurlInsteadOfShow = true,
    logRequestBody = false,
    logRequestHeaders = true,
    logResponseBody = false,
    logResponseHeaders = true,
    beforeRequestSendLogLevel = LogLevel.Warn,
    responseLogLevel = _ => LogLevel.Warn,
    responseExceptionLogLevel = LogLevel.Warn
  ))
)

```

---

<div class="post-metadata">

**Author:** ![kciesielski](https://dub1.discourse-cdn.com/flex005/user_avatar/softwaremill.community/kciesielski/32/133_2.png) [@kciesielski](https://softwaremill.community/u/kciesielski)\
**Post date:** [May 18, 2023, 11:24am UTC](https://softwaremill.community/t/java-17-missing-content-length-header-on-a-multipartfile-request/206/2 "2023-05-18T11:24:45Z")

</div>

@leszek The change is caused by Java HTTP Client, which is the underlying sender for your backend. I suspect that with Java version update it started to send multipart bodies as `chunked`, and, according to RFC, the `Content-Length` header is illegal for this content type ([http - Chunked encoding and content-length header - Stack Overflow](https://stackoverflow.com/a/3304186)).  
There’s also an interesting rationale on [Wikipedia](https://www.wikiwand.com/en/Chunked_transfer_encoding):

> Chunked transfer encoding allows a server to maintain an [HTTP persistent connection](https://www.wikiwand.com/en/HTTP_persistent_connection) for dynamically generated content. In this case, the HTTP Content-Length header cannot be used to delimit the content and the next HTTP request/response, as the content size is not yet known. Chunked encoding has the benefit that it is not necessary to generate the full content before writing the header, as it allows streaming of content as chunks and explicitly signaling the end of the content, making the connection available for the next HTTP request/response.

Your receiving server seems to be incorrectly handling the request, if it requires the header to be present.  
I don’t think there’s a reliable method that you could use to calculate content length of the chunks and add the header by yourself in this case.

Regarding `Slf4jLoggingBackend`, I’ll check this issue separately.

---

<div class="post-metadata">

**Author:** ![leszek](https://avatars.discourse-cdn.com/v4/letter/l/82dd89/32.png) [@leszek](https://softwaremill.community/u/leszek)\
**Post date:** [May 18, 2023, 11:29am UTC](https://softwaremill.community/t/java-17-missing-content-length-header-on-a-multipartfile-request/206/3 "2023-05-18T11:29:20Z")

</div>

Thank you @kciesielski .

Yes, I found similar information too. I also read that `Transfer-Encoding: chunked` is used only if the size of the body is unknown, but that is not the case here. I have the file and the size is known.

Would it be possible to check this case? Could it be some misconfiguration from the STTP itself?

---

<div class="post-metadata">

**Author:** ![kciesielski](https://dub1.discourse-cdn.com/flex005/user_avatar/softwaremill.community/kciesielski/32/133_2.png) [@kciesielski](https://softwaremill.community/u/kciesielski)\
**Post date:** [May 18, 2023, 11:33am UTC](https://softwaremill.community/t/java-17-missing-content-length-header-on-a-multipartfile-request/206/4 "2023-05-18T11:33:27Z")

</div>

It’s up to the Java Http client to decide to chunk, and then it assumes that the size is unknown. It’s the internal logic of this client on which sttp doesn’t have any influence.

However, there may be a workaround. Sttp allows to instance the Java client manually

```auto
import java.net.http.HttpClient
val httpClient: HttpClient = ???
val backend = HttpClientZioBackend.usingClient(httpClient)

```

maybe there’s a possibility to configure it to disable this chunking behavior.

---

<div class="post-metadata">

**Author:** ![leszek](https://avatars.discourse-cdn.com/v4/letter/l/82dd89/32.png) [@leszek](https://softwaremill.community/u/leszek)\
**Post date:** [May 18, 2023, 11:34am UTC](https://softwaremill.community/t/java-17-missing-content-length-header-on-a-multipartfile-request/206/5 "2023-05-18T11:34:30Z")

</div>

Thank you, I will explore this idea.

---

<div class="post-metadata">

**Author:** ![leszek](https://avatars.discourse-cdn.com/v4/letter/l/82dd89/32.png) [@leszek](https://softwaremill.community/u/leszek)\
**Post date:** [May 18, 2023, 3:37pm UTC](https://softwaremill.community/t/java-17-missing-content-length-header-on-a-multipartfile-request/206/6 "2023-05-18T15:37:45Z")

</div>

For the record. I ended up using `HttpURLConnectionBackend` and wrap it around the ZIO effect.  
This backend produces the `Content-Length` header.

---

<div class="post-metadata">

**Author:** ![kciesielski](https://dub1.discourse-cdn.com/flex005/user_avatar/softwaremill.community/kciesielski/32/133_2.png) [@kciesielski](https://softwaremill.community/u/kciesielski)\
**Post date:** [May 18, 2023, 8:41pm UTC](https://softwaremill.community/t/java-17-missing-content-length-header-on-a-multipartfile-request/206/7 "2023-05-18T20:41:41Z")

</div>

Sounds good, fortunately there is some flexibility when it comes to backends 🙂  
If this backend uses `content-length` then I suspect it doesn’t use `transfer-encoding: chunked`?

---

<div class="post-metadata">

**Author:** ![leszek](https://avatars.discourse-cdn.com/v4/letter/l/82dd89/32.png) [@leszek](https://softwaremill.community/u/leszek)\
**Post date:** [May 19, 2023, 6:41am UTC](https://softwaremill.community/t/java-17-missing-content-length-header-on-a-multipartfile-request/206/8 "2023-05-19T06:41:29Z")

</div>

Exactly. These headers are exclusive.

---

<div class="post-metadata">

**Author:** ![kciesielski](https://dub1.discourse-cdn.com/flex005/user_avatar/softwaremill.community/kciesielski/32/133_2.png) [@kciesielski](https://softwaremill.community/u/kciesielski)\
**Post date:** [May 19, 2023, 12:01pm UTC](https://softwaremill.community/t/java-17-missing-content-length-header-on-a-multipartfile-request/206/9 "2023-05-19T12:01:40Z")

</div>

Regarding logging of GET requests, but no POST requests via Slf4j, I could not reproduce the issue.  
Here’s a small program I wrote that can be run with `scala-cli`: [SttpZioLog.scala · GitHub](https://gist.github.com/kciesielski/da7b849f5c179d8d73b2ab562465007b)  
I tried with different kinds of responses and status codes (with requestbin) and with an entirely failing the effect with an unknown host.  
Maybe your issue is caused by some specific configuration of sttp or your logging backend, but I would need to know more about this specific case.

---

<div class="post-metadata">

**Author:** ![leszek](https://avatars.discourse-cdn.com/v4/letter/l/82dd89/32.png) [@leszek](https://softwaremill.community/u/leszek)\
**Post date:** [May 21, 2023, 3:28pm UTC](https://softwaremill.community/t/java-17-missing-content-length-header-on-a-multipartfile-request/206/10 "2023-05-21T15:28:51Z")

</div>

Thank you @kciesielski for your time and checking this. I’ve checked our other POST sttp calls and the logging works, but the POST upload call mentioned above does not and I cannot find any reasonable difference.

I tried to replicate our settings in your code example, but the POST log was always working.

If I manage to find it, I will start a new discussion or report an issue.

Thank you
