【问题标题】:Can http4s do different status codes given a Future?http4s 可以在给定 Future 的情况下执行不同的状态代码吗?
【发布时间】:2017-10-04 21:17:09
【问题描述】:

我正在使用http4s,并且我有一个Try,它会为响应生成一些json数据:

case GET -> Root / "something" =>
   getSomethingTry() match {
    case Success(something) => Ok(something)
    case Failure(CustomNotFoundException(reason)) => NotFound(reason)
    case Failure(CustomConflictException()) => Conflict()
   }

此函数正确返回Task[Response]

但是,我想将 Try 替换为 Future。匹配不再起作用,因为未来可能在匹配时尚未解决。所以,我可以描绘未来:

case GET -> Root / "something" =>
   getSomethingFuture().map {
    something => Ok(something)
   }.recover {
    case CustomNotFoundException(reason) => NotFound(reason)
    case CustomConflictException() => Conflict()
   }

但这会返回一个Future[Task[Response]],这不是http4s 想要的。使用Await.result 来拆箱Future 似乎不合适——我认为这可能会导致线程池问题——但它确实使代码工作。

http4s 接受期货作为任务创建者的参数:

case GET -> Root / "something" =>
   Ok(getSomethingFuture())

但这并不能让我在出现不同错误时设置不同的状态代码。一个解决方案可能是在一项任务上执行.recover,但我看不到明显的方法。

如果出现不同的Future 失败案例,我如何调用不同的http4s 任务包装器?我需要使用中间件吗?

【问题讨论】:

    标签: scala task future http4s


    【解决方案1】:

    假设您使用的是http4s 0.17 或更高版本,您的Taskfs2.Task

    很容易将Future转换成Task再处理后者:

    case GET -> Root / "something" =>
       Task.fromFuture(getSomethingFuture())
         .flatMap {
           something => Ok(something)
         }
         .handleWith {
           case CustomNotFoundException(reason) => NotFound(reason)
           case CustomConflictException() => Conflict()
         }
    

    不过,我建议在整个程序中使用Task,而不是TryFuture

    【讨论】:

    • 这太好了,谢谢。尝试这段代码说我需要一个隐含的Strategy - 有什么理由我不应该这样做:implicit val strategy = Strategy.fromCachedDaemonPool()
    • @TimothyJones 你可以做到。我更喜欢使用默认的标准 Future - Strategy.fromExecutionContext(scala.concurrent.ExecutionContext.global),但您可以稍后对其进行微调(只是不要为每个服务创建新策略 :)
    • 谢谢!我们拥有的fs2 版本没有默认值,所以我需要提供一个。
    【解决方案2】:

    你真的不需要解开未来。 Play 框架提供了用于返回 Future 的 action.async。

    您可以通过以下方式使用它

    Action.async {
      getSomethingFuture().map {
        something => Ok(something)
       }.recover {
        case CustomNotFoundException(reason) => NotFound(reason)
        case CustomConflictException() => Conflict()
       }
    }
    

    https://www.playframework.com/documentation/2.6.x/ScalaAsync#returning-futures

    【讨论】:

    • http4s 没有播放。
    • 我同意 Oleg - 这会产生一个 Action,这在这一点上是不合适的(并且 Ok() 等的助手也没有正确的类型)
    猜你喜欢
    • 2017-10-27
    • 2018-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-08
    • 1970-01-01
    • 2011-03-28
    • 2021-02-26
    相关资源
    最近更新 更多