scalaziohttp4shttp4s-circe

HTTP4S EntityEncoder


I have created HttpRoutes for ZIO app

class BlockChainAPI[R <: BlockChain] {
  type BlockChainTask[A] = RIO[R, A]
  private val dsl = Http4sDsl[BlockChainTask]

  import dsl._

  implicit def jsonDecoder[A](implicit decoder: Decoder[A]): EntityDecoder[BlockChainTask, A] = jsonOf[BlockChainTask, A]

  implicit def jsonEncoder[A](implicit encoder: Encoder[A]): EntityEncoder[BlockChainTask, A] = jsonEncoderOf[BlockChainTask, A]

  val routes: HttpRoutes[BlockChainTask] = HttpRoutes.of[BlockChainTask] {

    case GET -> Root / "message" / message =>
      val newMessage = BlockMessage(message)
      BlockChain
        .addBlock(Seq(newMessage))
        .foldZIO(
          err => BadRequest(err.getMessage),
          _ => Ok(s"Message $message added")
        )
  }
}

and it works fine! But today I've added a new route:

    case GET -> Root =>
      StaticFile.fromPath(fs2.io.file.Path("/api-docs/index.html")).getOrElse(NotFound()).foldZIO(
        err => InternalServerError(err.getMessage),
        result => Ok(result)
      )

and it fails with error: Cannot convert from Product with java.io.Serializable to an Entity, because no EntityEncoder[[A]zio.ZIO[R,Throwable,A], Product with java.io.Serializable] instance could be found.

Maybe someone knows how to fix it?!

I added:

implicit def jsonEncoder2[A <: Product with Serializable](implicit encoder: Encoder[A]): EntityEncoder[BlockChainTask, A] = jsonEncoderOf[BlockChainTask, A]

but it doesn't work


Solution

  • Your result has a Product with Serializable type, which is not something http4s knows how to encode it in the HTTP response.

    This is because StaticFile.fromPath(fs2.io.file.Path("/api-docs/index.html")).getOrElse(NotFound()) actually gives you 2 unrelated types depending on whether you go through the nominal path or the getOrElse path.

    You need to return a consistent type in both paths, or don't use getOrElse at this stage, or move the missing case to the error channel.

    Using intermediate variables with explicit types should help you.