【问题标题】:How to get Http[F] out of the context F?如何让 Http[F] 脱离上下文 F?
【发布时间】:2020-07-04 23:35:54
【问题描述】:

我正在尝试在码头上运行基于http4s 的网络应用程序。 http4s库提供AsyncHttp4sServlet[IO]类来扩展,我使用如下:

class UserSvcServlet
    extends AsyncHttp4sServlet[IO](
      service = UserSvcServer.start,
      servletIo = BlockingServletIo(4096, Blocker.liftExecutorService(Executors.newCachedThreadPool())),
      serviceErrorHandler = DefaultServiceErrorHandler
    )

正如您在 service 属性中看到的,我提供的 http 服务具有以下实现:

def start[F[_]: ConcurrentEffect: ContextShift: Sync: Timer]: HttpApp[F] =
for {

  a <- EnvironmentLoader.db.load[F].map(create_transactor)
  b <- EnvironmentLoader.cors.load[F].map(origin)
       http = Logger.httpApp(true, true)(CORS(UserRoutes(UserProgram(LiveUserQuery.make(a))).routes, b).orNotFound)
} yield http

start 方法应该返回 HttpApp[F],但不幸的是 for 块返回 F[Http[F]]。但是最后F 将是IO 类型。

这里是HttpApp[F]的定义:

type Http[F[_], G[_]] = Kleisli[F, Request[G], Response[G]]  

EnvironmentLoader.db.load[F].map(create_transactor)EnvironmentLoader.cors.load[F].map(origin) 都在 F 的上下文中,它们加载环境变量。对于加载环境变量,我使用库https://cir.is/

我知道,不可能将Http[F] 脱离上下文F。我必须在这里重组代码以使其工作吗?

更新

一种可能的解决方法是:

class UserSvcServlet
    extends AsyncHttp4sServlet[IO](
      service = UserSvcServer.start[IO].unsafeRunSync(),
      servletIo = BlockingServletIo(4096, Blocker.liftExecutorService(Executors.newCachedThreadPool())),
      serviceErrorHandler = DefaultServiceErrorHandler
    )

虽然很丑,但是很管用。

【问题讨论】:

    标签: scala servlets scala-cats http4s


    【解决方案1】:

    是的,你必须这样做。

    当您拥有F[Http[F]] 时,您应该将其组合到您的 IO 程序中:

    for {
      dep1 <- createDependency1
      dep1 <- createDependency2
      http <- createHttp // : F[HttpApp[F]] = F[Request[F] => F[Response[F]]]
                         // or "use side effects to create a function that
                         // will take side-effecting request to create
                         // recipe for side-effecting response" (e.g.
                         // reading from stream to server and returning
                         // a stream from server)
      dep4 =  needHttp(http)
      ...
    } yield ...
    

    在您的代码中,从 F[HttpApp[F]] 更改为 HttpApp[F] 似乎实际上只需要更改:

    http = ...
    

    进入

    http <- ...
    

    哪种暗示,你没有足够注意你的代码做什么。

    【讨论】:

    • 我现在不能,因为UserSvcServlet 需要HttpApp[F] 而我不能在for 块内调用类。
    • 然后移出它的外部初始化并传递一些已经初始化的东西..
    • 我忘了说,class UserSvcServlet 是世界末日。可以和typelevel.org/cats-effect/datatypes/ioapp.html比较。该应用程序将在 Jetty 上运行。
    • 不能移到外面。
    猜你喜欢
    • 2020-04-16
    • 2012-01-15
    • 1970-01-01
    • 1970-01-01
    • 2014-07-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-14
    相关资源
    最近更新 更多