softwaremill / sttp

The Scala HTTP client you always wanted!
https://sttp.softwaremill.com
Apache License 2.0
1.45k stars 309 forks source link

Receives an Either when a String is expected when using `response(asStringAlways)` #389

Closed ithinkicancode closed 4 years ago

ithinkicancode commented 4 years ago

The following code example should demonstrate the problem. I'm using Ammonite.

{
  import $ivy.`dev.zio::zio-streams:1.0.0-RC17`
  import $ivy.`com.softwaremill.sttp.client::core:2.0.0-RC5`
  import $ivy.`com.softwaremill.sttp.client::async-http-client-backend-zio:2.0.0-RC5`

  import sttp.client._

  val zioRuntime = new zio.DefaultRuntime {}

  implicit val alwaysFailingBackend = {
    val zioBackend = zioRuntime.unsafeRun(
      asynchttpclient.zio.AsyncHttpClientZioBackend()
    )

    testing.SttpBackendStub(zioBackend)
      .whenAnyRequest.thenRespondServerError
  }

  val test = basicRequest
    .get(uri"http://localhost")
    .response(asStringAlways)
    .send()
    .map { response => 
      val content = response.body
      val statusCode = response.code.code

      s"Status code $statusCode: $content"
    }

  zioRuntime.unsafeRun(test)
}

Running this snippet will result in the following error:

java.lang.ClassCastException: class scala.util.Left cannot be cast to class java.lang.String

If you change the test to the following:

{
  ...
  val test = basicRequest
    .get(uri"http://localhost")
    .response(asStringAlways)
    .send()
    .map { response => 
      val statusCode = response.code.code

      s"Status code $statusCode"
    }

  zioRuntime.unsafeRun(test)
}

This will succeed, returning "Status code 500"

The type signature of asStringAlways guarantees to return a ResponseAs[String, Nothing]; however, when processing the response body of a HTTP call, an Either is returned hence the ClassCastException.

adamw commented 4 years ago

Should be fixed in 2.0.0-RC6