Akka HighLevelHttp return 恢复未来的路线
Akka HighLevelHttp return Route from recovering Future
因为我有一个请求主体,所以我需要将其作为未来获取并在操作后发送响应。但是,我需要检查主体是否有效,如果不是,我想 return BadRequest 状态。
我知道是代码太多了,所以请看里面的requestFuture
,在recover函数里面是问题。
(pathPrefix("api" / "search") & post & extractRequest) { request =>
val tokenResult = request.headers.find(x => x.name.toLowerCase == "token")
tokenResult match {
case None => throw new IllegalArgumentException(ServerMessages.TOKEN_NOT_FOUND)
case Some(token) => token.value match {
case this.apiToken => {
val entity = request.entity
val strictEntityFuture = entity.toStrict(2 seconds)
val requestFuture = strictEntityFuture
.map(_.data.utf8String.parseJson
.convertTo[SearchFilters])
requestFuture map { filters =>
// here - I return an Route with data from controller
complete(controller.searchData(filters)
.map(_.toJson.prettyPrint)
.map(toHttpEntity)))
} recover (e => {
// HERE IS THE PROBLEM
// I need to return an Route, but here will be a Future[Route]
complete(400 -> ServerMessages.INVALID_REQUEST_BODY)
}
}
case _ => throw new IllegalArgumentException(ServerMessages.INVALID_TOKEN)
}
}
我需要解压来自未来的响应,或者使用其他方式抛出错误。
找到了使用 onComplete
指令的解决方案,但我需要知道我的 json 是否成功转换,以便抛出自定义错误。
onComplete(requestFuture) {
case Success(filters) => searchKpi(filters) ~
pathEndOrSingleSlash {
complete(403 -> ServerMessages.INVALID_METHOD_ARGUMENTS)
}
case Failure(ex) => failWith(ex) // returns 500 Internal Server Error
}
谢谢
试试这样的东西:
val requestFuture = strictEntityFuture
requestFuture.map { entity =>
entity.data.utf8String match {
// Do your processing here
case "" => RouteResult.Complete(HttpResponse(StatusCode.int2StatusCode(200), entity = HttpEntity("OK")))
}}.recover {
case err: Throwable =>
RouteResult.Complete(HttpResponse(StatusCode.int2StatusCode(500), entity = HttpEntity(err.getMessage)))
}
您可以使用 ExceptionHandler.
像在文档中那样定义异常处理程序,并将异常中的一个案例(应该与 failWith
抛出的相同)添加到您需要 return 的 HTTP 状态(您提及 BadRequest
)
case class MyBadException() extends RuntimeException
implicit def myExceptionHandler: ExceptionHandler =
ExceptionHandler {
case MyBadException() => complete(HttpResponse(BadRequest)) // You decide the HTTP status to return
case _ => complete(HttpResponse(InternalServerError, entity = "Bad numbers, bad result!!!"))
}
val route = path("test") {
onComplete(getSomething()) {
case Success(v) => complete("Ok")
case Failure(err) => failWith(MyBadException())
}
}
请注意,您有两种方法来附加异常处理程序
来自文档:
Bring it into implicit scope at the top-level.
Supply it as argument to the handleExceptions directive.
我已经有一个 Exception Handle
r,但只有 2 个案例(IllegalArgument
或 NoSuchElement
)。多亏了 ccheneson,我扩展了我的处理程序,可以 return 一个 BadRequest
响应。但是我在那里做错了,因为我的 BadRequestException
被打包到 defaultExceptionHandler
路由。
val routes = (
handleExceptions(noSuchElementExceptionHandler) &
handleExceptions(tokenNotFoundExceptionHandler)) {
domainRoutes
}
private val domainRoutes = {
onComplete(future) {
case Success(values) => complete(controller.getdata(values))
case Failure(e) => failWith(BadRequestExceptionHandler(e.getMessage))
}
}
因为我有一个请求主体,所以我需要将其作为未来获取并在操作后发送响应。但是,我需要检查主体是否有效,如果不是,我想 return BadRequest 状态。
我知道是代码太多了,所以请看里面的requestFuture
,在recover函数里面是问题。
(pathPrefix("api" / "search") & post & extractRequest) { request =>
val tokenResult = request.headers.find(x => x.name.toLowerCase == "token")
tokenResult match {
case None => throw new IllegalArgumentException(ServerMessages.TOKEN_NOT_FOUND)
case Some(token) => token.value match {
case this.apiToken => {
val entity = request.entity
val strictEntityFuture = entity.toStrict(2 seconds)
val requestFuture = strictEntityFuture
.map(_.data.utf8String.parseJson
.convertTo[SearchFilters])
requestFuture map { filters =>
// here - I return an Route with data from controller
complete(controller.searchData(filters)
.map(_.toJson.prettyPrint)
.map(toHttpEntity)))
} recover (e => {
// HERE IS THE PROBLEM
// I need to return an Route, but here will be a Future[Route]
complete(400 -> ServerMessages.INVALID_REQUEST_BODY)
}
}
case _ => throw new IllegalArgumentException(ServerMessages.INVALID_TOKEN)
}
}
我需要解压来自未来的响应,或者使用其他方式抛出错误。
找到了使用 onComplete
指令的解决方案,但我需要知道我的 json 是否成功转换,以便抛出自定义错误。
onComplete(requestFuture) {
case Success(filters) => searchKpi(filters) ~
pathEndOrSingleSlash {
complete(403 -> ServerMessages.INVALID_METHOD_ARGUMENTS)
}
case Failure(ex) => failWith(ex) // returns 500 Internal Server Error
}
谢谢
试试这样的东西:
val requestFuture = strictEntityFuture
requestFuture.map { entity =>
entity.data.utf8String match {
// Do your processing here
case "" => RouteResult.Complete(HttpResponse(StatusCode.int2StatusCode(200), entity = HttpEntity("OK")))
}}.recover {
case err: Throwable =>
RouteResult.Complete(HttpResponse(StatusCode.int2StatusCode(500), entity = HttpEntity(err.getMessage)))
}
您可以使用 ExceptionHandler.
像在文档中那样定义异常处理程序,并将异常中的一个案例(应该与 failWith
抛出的相同)添加到您需要 return 的 HTTP 状态(您提及 BadRequest
)
case class MyBadException() extends RuntimeException
implicit def myExceptionHandler: ExceptionHandler =
ExceptionHandler {
case MyBadException() => complete(HttpResponse(BadRequest)) // You decide the HTTP status to return
case _ => complete(HttpResponse(InternalServerError, entity = "Bad numbers, bad result!!!"))
}
val route = path("test") {
onComplete(getSomething()) {
case Success(v) => complete("Ok")
case Failure(err) => failWith(MyBadException())
}
}
请注意,您有两种方法来附加异常处理程序
来自文档:
Bring it into implicit scope at the top-level. Supply it as argument to the handleExceptions directive.
我已经有一个 Exception Handle
r,但只有 2 个案例(IllegalArgument
或 NoSuchElement
)。多亏了 ccheneson,我扩展了我的处理程序,可以 return 一个 BadRequest
响应。但是我在那里做错了,因为我的 BadRequestException
被打包到 defaultExceptionHandler
路由。
val routes = (
handleExceptions(noSuchElementExceptionHandler) &
handleExceptions(tokenNotFoundExceptionHandler)) {
domainRoutes
}
private val domainRoutes = {
onComplete(future) {
case Success(values) => complete(controller.getdata(values))
case Failure(e) => failWith(BadRequestExceptionHandler(e.getMessage))
}
}