喷涂路由404响应

时间:2013-03-11 19:37:44

标签: scala akka spray

我有一个服务,它在Future中返回一个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
        }
      }
    }
  }

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

2 个答案:

答案 0 :(得分:17)

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

您的路线看起来就像这样:

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

当然,您可以将rejectEmptyResponse放在路径中,具体取决于您是否要用它包装更多的路径部分。

更多信息:

答案 1 :(得分: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
}

当然你可以选择你喜欢的Exception,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]
}

通过这种方式,您可以处理我在未来结果中出现的几种不同错误。