如何以编程方式执行拒绝处理程序的路由并获得生成的 HttpEntity?

How can I programmatically execute Route of rejection handler and get resulting HttpEntity?

如何以编程方式执行拒绝处理程序的 Route 并获得结果 HttpEntity

例如,假设我有 RequestContext 对象和 Rejection 对象,我想对其执行 RejectionHandler.default 并获得 HttpEntity.

这是我想做的事的例子:

implicit def myRejectionHandler =
  RejectionHandler.newBuilder()
    .handleAll[Rejection] { rejections ⇒

    def prefixEntity(entity: ResponseEntity): ResponseEntity = entity match {
      case HttpEntity.Strict(contentType, data) => {
        import spray.json._
        val text = ErrorResponse(0, "Rejection", data.utf8String).toJson.prettyPrint
        HttpEntity(ContentTypes.`application/json`, text)
      }
      case _ =>
        throw new IllegalStateException("Unexpected entity type")
    }

    val route: Route = extractRequestContext { ctx =>
      mapResponseEntity(prefixEntity) {
        // Here I want result of `complete` route from RejectionHandler.default
      }
    }
    route
  }
    .handleNotFound {
      complete((NotFound, "Not here!"))
    }
    .result()

我想我明白了你想要的要点。您可以在您的评论所在的位置应用默认的拒绝处理程序。唯一的问题是 apply 那里 returns 和 Option 如果遇到的拒绝没有命中该拒绝处理程序中的任何内容,那将是 None。这不太可能,因为您使用的是默认处理程序并且它几乎可以处理所有事情,但您仍然需要在代码中考虑它(因此我的 getOrElse 导致通用 InternalServerError)。修改后的代码如下所示:

val defaultRejectionHandler = RejectionHandler.default

implicit def myRejectionHandler =
  RejectionHandler.newBuilder()
    .handleAll[Rejection] { rejections ⇒

    def prefixEntity(entity: ResponseEntity): ResponseEntity = entity match {
      case HttpEntity.Strict(contentType, data) => {
        import spray.json._
        val text = ErrorResponse(0, "Rejection", data.utf8String).toJson.prettyPrint
        HttpEntity(ContentTypes.`application/json`, text)
      }
      case _ =>
        throw new IllegalStateException("Unexpected entity type")
    }

    val route: Route = extractRequestContext { ctx =>
      mapResponseEntity(prefixEntity) {
        defaultRejectionHandler.apply(rejections).getOrElse{
          complete(StatusCodes.InternalServerError)
        }
      }
    }
    route
  }
  .handleNotFound {
    complete((NotFound, "Not here!"))
  }
  .result()

这可以编译,但我没有实际测试它是否能达到预期的效果。此外,我不需要 RequestContextctx,因此您可以删除其中的 extractRequestContext 层。