Skip to content

http4s client tries to re-run body stream, possibly uses disposed connection #391

@fiadliel

Description

@fiadliel

_executeRequest is defined like this:

    def _executeRequest[T, U](
      method: String,
      path: Seq[String],
      queryParameters: Seq[(String, String)] = Nil,
      requestHeaders: Seq[(String, String)] = Nil,
      body: Option[T] = None
    )(handler: org.http4s.Response[F] => F[U]
    )(implicit encoder: io.circe.Encoder[T]): F[U] = {

and uses the fetch method of the http4s client:

      httpClient.fetch(modifyRequest(authBody))(handler)

If we look at the scaladoc for fetch:

def fetch[A](req: Request[F])(f: (Response[F]) ⇒ F[A]): F[A]
Submits a request, and provides a callback to process the response.

req
The request to submit

f
A callback for the response to req. The underlying HTTP connection is disposed when the returned task completes. Attempts to read the response body afterward will result in an error.

returns
The result of applying f to the response to req

This means you should not access the body after this point in the code.

However, when an expected error occurs, the response is given back, including a call which tries to parse JSON in a lazy val. This is fundamentally unsafe for two reasons:

  1. the connection could already have been disposed before the lazy val is evaluated (which is outside of the fetch block).
  2. if the body has already been consumed, in a streaming situation, you cannot restart streaming. This might not have been done in some cases, but it's a fiddly thing to keep track of.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions