Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Empty body sent when using Http4sBackend with circe JSON body with JdkHttpClient #1970

Open
astridej opened this issue Oct 11, 2023 · 0 comments

Comments

@astridej
Copy link

Minimal example to reproduce

import cats.effect.{IO, IOApp}
import io.circe.Encoder
import org.http4s.circe.CirceEntityCodec.*
import org.http4s.jdkhttpclient.JdkHttpClient
import sttp.client3.*
import sttp.client3.circe.*
import sttp.client3.http4s.Http4sBackend

object Main extends IOApp.Simple {
  case class Test(foo: String) derives io.circe.Encoder.AsObject

  override def run: IO[Unit] = {
    for {
      client <- JdkHttpClient.simple[IO]
      sttpBackend = Http4sBackend.usingClient(client)
      req = basicRequest.put(uri"<some uri goes here>")
        .body(Test("bar"))
      _ <- req.send(sttpBackend)
    } yield ()
  }
}

Despite the fact that we set a request body, it is not sent to the server. If we set the JDK client logging to log requests and headers, we see it is sending a Content-Length of 0:

Oct 11, 2023 5:31:06 PM jdk.internal.net.http.Http1Request logHeaders
INFO: HEADERS: REQUEST HEADERS:
PUT / HTTP/1.1
Content-Length: 0
Host: <uri>
User-Agent: Java-http-client/21
Accept-Encoding: gzip, deflate
Content-Type: application/json; charset=utf-8

Cause

A coworker and I spent some time debugging this because it was so surprising. The cause seems to be the fact that the Content-Length header is not generated when you add a body using the circe BodySerializer (unlike if you set a raw string body). This then produces a http4s request without content-length header, which is passed to the JDK http client via the http4s wrapper. The JDK client in turn seems to have a problem where it needs all the content headers to be present: it somehow falls back to 0 content-length and does not send the body. (This was true on all versions of Java I tried.)

I admit that I'm not sure what point in the chain would be the right place to start fixing this, or whether a similar issue might affect any other backends that end up using a JDK http client in the end.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant