在给出Future的情况下,http4可以执行不同的状态代码吗?

时间:2017-10-04 00:26:57

标签: scala task future http4s

我正在使用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任务包装器?我需要使用中间件吗?

2 个答案:

答案 0 :(得分:2)

假设您使用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

答案 1 :(得分:-1)

你真的不需要打开未来。 Play框架提供action.async以返回Future。

您可以按以下方式使用

private class CustomFilter : IActionFilter
{
    private readonly MainDbContext _mainDbContext;

    public CustomFilter(MainDbContext mainDbContext)
    {
        _mainDbContext = mainDbContext;
    }

    public void OnActionExecuting(ActionExecutingContext context)
    {
        var model = _mainDbContext.Groups.ToList();
        context.Result = new ViewResult { ViewName = "Index" };
    }

    public void OnActionExecuted(ActionExecutedContext context)
    {
    }
}

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