为什么 Akka HTTP 路由会捕获我的异常?
Why is Akka HTTP Routing Catching My Exception?
鉴于此代码
def leaderboardPost(name: Option[String]): Route =
post {
logRequest("leaderboard", Logging.DebugLevel) {
handleRejections(postBodyRejections) {
entity(as[LeaderboardPostRequest]) { leaderboard =>
try {
complete(leaderboardCreate(Some(leaderboard.name), Some(leaderboard.kind)))
} catch {
case cause: DuplicateIDException =>
logger.error(cause)
complete(cause.response)
case cause: UnknownKindException =>
logger.warn(cause)
complete(cause.response)
case cause: Throwable =>
logger.error(cause)
complete(HttpResponse(InternalServerError, entity = s"Exception thrown from LeaderboardPost: ${cause.getMessage}"))
}
}
}
}
}
当 leaderboardCreate
抛出 UnknownKindException
路由代码捕获它并将其转换为 Completing with 500 Internal Server Error response. To change default exception handling behavior, provide a custom ExceptionHandler.
虽然我正在考虑创建自定义 ExceptionHandler,但我不明白为什么需要这样做。我的代码应该捕获它,而不是 return complete(cause.response)
。 Akka HTTP 如何在我的代码捕获异常之前捕获异常?
根据我的理解,发生这种情况是因为 leaderboardCreate
实际上并未像您预期的那样与 complete
调用同步执行。 complete
方法 returns 扩展自 Route
的 StandardRoute
定义为:
type Route = RequestContext ⇒ Future[RouteResult]
换句话说,"route" 是从上下文到 Future
(RouteResult
)的函数。如果您查看 complete
定义,它就是:
def complete(m: ⇒ ToResponseMarshallable): StandardRoute =
StandardRoute(_.complete(m))
注意 ToResponseMarshallable
之前的 ⇒
。这是传递一个参数 by name 有效地将它变成惰性评估。
换句话说,你所有的 try/catch
包装都是非常小的(并且没有异常)构建 StandardRoute
的代码,它将你的逻辑捕获为惰性值,而不是逻辑本身的执行.这就是为什么你需要一个 custom ExceptionHandler ,你(或者更确切地说 Akka)实际上可以将它放入 Future
的错误处理程序链中,当它是 运行.
鉴于此代码
def leaderboardPost(name: Option[String]): Route =
post {
logRequest("leaderboard", Logging.DebugLevel) {
handleRejections(postBodyRejections) {
entity(as[LeaderboardPostRequest]) { leaderboard =>
try {
complete(leaderboardCreate(Some(leaderboard.name), Some(leaderboard.kind)))
} catch {
case cause: DuplicateIDException =>
logger.error(cause)
complete(cause.response)
case cause: UnknownKindException =>
logger.warn(cause)
complete(cause.response)
case cause: Throwable =>
logger.error(cause)
complete(HttpResponse(InternalServerError, entity = s"Exception thrown from LeaderboardPost: ${cause.getMessage}"))
}
}
}
}
}
当 leaderboardCreate
抛出 UnknownKindException
路由代码捕获它并将其转换为 Completing with 500 Internal Server Error response. To change default exception handling behavior, provide a custom ExceptionHandler.
虽然我正在考虑创建自定义 ExceptionHandler,但我不明白为什么需要这样做。我的代码应该捕获它,而不是 return complete(cause.response)
。 Akka HTTP 如何在我的代码捕获异常之前捕获异常?
根据我的理解,发生这种情况是因为 leaderboardCreate
实际上并未像您预期的那样与 complete
调用同步执行。 complete
方法 returns 扩展自 Route
的 StandardRoute
定义为:
type Route = RequestContext ⇒ Future[RouteResult]
换句话说,"route" 是从上下文到 Future
(RouteResult
)的函数。如果您查看 complete
定义,它就是:
def complete(m: ⇒ ToResponseMarshallable): StandardRoute =
StandardRoute(_.complete(m))
注意 ToResponseMarshallable
之前的 ⇒
。这是传递一个参数 by name 有效地将它变成惰性评估。
换句话说,你所有的 try/catch
包装都是非常小的(并且没有异常)构建 StandardRoute
的代码,它将你的逻辑捕获为惰性值,而不是逻辑本身的执行.这就是为什么你需要一个 custom ExceptionHandler ,你(或者更确切地说 Akka)实际上可以将它放入 Future
的错误处理程序链中,当它是 运行.