如何根据未来的结果在 spray-routing 中设置状态码和 headers

How to set status code and headers in spray-routing based on a future result

我正在使用 spray-routing 和 Akka 来定义像

这样的路由
def items = path("items") {
  get {
    complete {
      actor.ask(GetItems)(requestTimeout).mapTo[Either[NoChange, Items]] map {
         result => result match {
            case Left(_) => StatusCodes.NotModified
            case Right(items) => 
               // here I want to set an HTTP Response header based on a 
               // field within items -- items.revision
               items
         }
      }
    }
  }
}

actor.ask returns 映射到 Future[Either[NoChange, Items]] 的 Future。 "complete" 很乐意处理 Future[StatusCodes...] 或 Future[Items] 但我不确定如何在 Future 中设置 HTTP 响应 header。

如果 header 没有在 Future 中设置,那么我可以将 complete 包装在指令中,但如何在 complete 中设置 header?

我正在使用 Spray 1.2.0。

感谢任何正确方向的指点!

如果您尝试在 complete 内部执行此操作,内部表达式的所有分支都必须生成可以由 complete 编组的类型。

您可以尝试这样的结构来使其工作:

complete {
  actor.ask(GetItems)(requestTimeout).mapTo[Either[NoChange, Items]] map {
     result => result match {
        case Left(_) => StatusCodes.NotModified: ToResponseMarshallable
        case Right(items) => 
           // here I want to set an HTTP Response header based on a 
           // field within items -- items.revision

           val headers = // items...
           HttpResponse(..., headers = headers): ToResponseMarshallable
     }
  }
}

这确保您传递给 complete 的表达式类型是 Future[ToResponseMarshallable],它应该始终是可编组的。

不过,更好的方法是使用 onSuccess directive,它允许您在 future 完成后使用其他指令:

get {
  def getResult() = actor.ask(GetItems)(requestTimeout).mapTo[Either[NoChange, Items]]
  onSuccess(getResult()) {
    case Left(_) => complete(StatusCodes.NotModified)
    case Right(items) => 
      // do whatever you want, e.g.
      val extraHeaders = // items.revisions
      respondWithHeaders(extraHeaders) {
        complete(...)
      }
  }
}