ZLayer类型不匹配的Sttp客户端3



我使用ZLayer和Sttp Client(async(创建简单的http请求程序,但我发现类型不匹配错误,无法解决。有人能告诉我为什么会出现类型不匹配的错误吗?

我使用这些版本的scala&图书馆。

java->8.282.08.1-amzn

scala->s.13.5

dev.zio->1.0.7

com.softwaremill.sttp.client3->3.3.0

type mismatch;
found   : zio.ZLayer[sttp.client3.asynchttpclient.zio.SttpClient,Nothing,ZlayerAndSttp.HttpBin]
(which expands to)  zio.ZLayer[zio.Has[sttp.client3.SttpBackend[zio.Task,sttp.capabilities.zio.ZioStreams with sttp.capabilities.WebSockets]],Nothing,zio.Has[ZlayerAndSttp.HttpBin.Service]]
required: zio.ZLayer[ZlayerAndSttp.HttpBin,?,?]
(which expands to)  zio.ZLayer[zio.Has[ZlayerAndSttp.HttpBin.Service],?,?]
program.provideCustomLayer((AsyncHttpClientZioBackend.layer() >>> HttpBin.live) >>> HttpBin.live)

这是的全部代码

import zio._
import sttp.client3._
import sttp.client3.circe._
import sttp.client3.asynchttpclient.zio._
import io.circe.generic.auto._
import zio.console.Console

object ZlayerAndSttp extends App {
case class HttpBinResponse(origin: String, headers: Map[String, String])
type HttpBin = Has[HttpBin.Service]
object HttpBin {
trait Service {
def sendRequest: ZIO[HttpBin with SttpClient, Throwable, HttpBinResponse]
}
val live: ZLayer[SttpClient, Nothing, HttpBin] = ZLayer.succeed(new Service {
override def sendRequest: ZIO[HttpBin with SttpClient, Throwable, HttpBinResponse] = {
val request = basicRequest
.get(uri"https://httpbin.org/get")
.response(asJson[HttpBinResponse])
sendR(request).map(_.body).absolve.map(res => HttpBinResponse(res.origin, res.headers))
}
})
def sendRequest: ZIO[HttpBin with SttpClient, Throwable, HttpBinResponse] = ZIO.accessM(_.get.sendRequest)
}
val request = basicRequest
.get(uri"https://httpbin.org/get")
.response(asJson[HttpBinResponse])
override def run(args: List[String]): URIO[zio.ZEnv, ExitCode] = {
val program = for {
result <- HttpBin.sendRequest
_ <- console.putStrLn(s"${result.origin}, ${result.headers}")
} yield ()
program.provideCustomLayer((AsyncHttpClientZioBackend.layer() >>> HttpBin.live) >>> HttpBin.live) // type mismatch
.exitCode
// ↓these lines of code run with no errors but I can't understand why
//    val program: ZIO[Console with SttpClient, Throwable, Unit] = for {
//      response <- send(request)
//      _ <- console.putStrLn(s"${response.body.toString}")
//    } yield ()
//    program.provideCustomLayer(AsyncHttpClientZioBackend.layer()).exitCode
}
}

你似乎让你的生活变得比需要的更复杂了。

最终代码的外观取决于您想要在这里实现什么。如果您试图在HttpBin接口后面隐藏Sttp的使用,那么您的层定义应该看起来像:

val live: ZLayer[SttpClient, Nothing, HttpBin] = 
(for {
client <- ZIO.environment[SttpClient]
} yield new Service {
override def sendRequest: ZIO[Any, Throwable, HttpBinResponse] = {
val request = basicRequest
.get(uri"https://httpbin.org/get")
.response(asJson[HttpBinResponse])
sendR(request)
.map(_.body)
.absolve
.map(res => HttpBinResponse(res.origin, res.headers))
.provide(client)
}
}).toLayer

然后您的访问器方法变为:

def sendRequest: ZIO[HttpBin, Throwable, HttpBinResponse] = 
ZIO.accessM(_.get.sendRequest)

你可以使用它:

override def run(args: List[String]): URIO[zio.ZEnv, ExitCode] = {
val program = for {
result <- HttpBin.sendRequest
_ <- console.putStrLn(s"${result.origin}, ${result.headers}")
} yield ()
program
.provideCustomLayer(AsyncHttpClientZioBackend.layer() >>> HttpBin.live)
.exitCode

这里需要注意的是,对于层组合,我只使用垂直运算符,因为HttpBin.live依赖于具有SttpClient的层;隐藏";这一事实来自调用方法,因此您可以创建HttpBintest变体,如果需要,该变体不需要Sttp。

如果你不需要隐藏信息,你可以完全去掉中间层,把sendRequest当作一个独立的方法。

object HttpBin {
def sendRequest: ZIO[SttpClient, Throwable, HttpBinResponse] = {
val request = basicRequest
.get(uri"https://httpbin.org/get")
.response(asJson[HttpBinResponse])
sendR(request)
.map(_.body)
.absolve
.map(res => HttpBinResponse(res.origin, res.headers))
}

然后您可以调用这个方法,所需要做的就是提供SttpClient层。

相关内容

  • 没有找到相关文章

最新更新