16

我有一项服务在未来返回 Option[ProductDoc] (作为 akka 询问)

如何在喷涂路由中响应,以便有效产品响应产品但未知但格式良好的产品返回 404?

我希望代码在这里填补空白:

get {
    path("products" / PathElement) { productID:String =>
      val productFuture = (productService ? ProductService.Get(productID)).mapTo[Option[ProductDoc]]

      // THE CODE THAT GOES HERE SO THAT
      // IF PRODUCT.ISDEFINED RETURN PRODUCT ELSE REJECT

    }
}

我可以开始工作的唯一方法就是使用这种可憎的东西:

get {
    path(PathElement) { productID:String =>
      val productFuture = (productService ? ProductService.Get(productID)).mapTo[Option[ProductDoc]]
      provide(productFuture).unwrapFuture.hflatMap {
        case x => provide(x)
      } { hResponse:shapeless.::[Option[ProductDoc], HNil] =>
        hResponse.head match {
          case Some(product) => complete(product)
          case None => reject
        }
      }
    }
  }

这肯定不是实现这一目标的正确方法吗?这似乎是一个非常简单的模式,一定已经有人解决了!

4

2 回答 2

17

Spray 已经支持您的用例:默认情况下将选项值None编组为EmptyEntity。这可能是您在进行任何更改之前所看到的:带有空文档的 200。有一个指令可以将空文档转换为 404, rejectEmptyResponse,您可以将其包裹在您想要此行为的部分路径中。

您的路线将如下所示:

  rejectEmptyResponse {
    path("products" / PathElement) { productID:String =>
      val productFuture = // same as before
      complete(productFuture)
    }
  }

当然,你可以rejectEmptyResponse根据你是否想用它包裹更多的路线部分来把路径放在里面。

更多信息:

于 2013-03-12T09:23:09.107 回答
0

几天前我遇到了同样的问题并提出了这个解决方案:

我将此方法添加到我的演员

def failIfEmpty[T](item: Future[Option[T]], id: String) = {
    (item map {
      case Some(t) => t
      case None => throw NotFoundException(Message(s"id '$id' could not be        found",`ERROR`))
    }) pipeTo sender
}

当然你可以选择一个你喜欢的异常,NotFoundException是我自己的一个......

在你的结果上调用这个来回答你的演员的问题(这是一个使用 ReactiveMongo 的例子,collection.find(query).headOption用你的替换Future[Option]):

failIfEmpty(collection.find(query).headOption, id)

然后将 ExceptionHandler 添加到您的服务(定义路由的位置),如下所示:

implicit val klaraExceptionHandler = ExceptionHandler.fromPF {
    case InternalServerErrorException(messages) => complete(InternalServerError, messages)
    case NotFoundException(message) => complete(NotFound, message)
    case ValidationException(messages) => complete(PreconditionFailed, messages)
    [and so on]
}

这样,您可以处理我在未来结果中出现的几个不同的错误。

于 2013-03-12T08:07:13.117 回答