Почему Akka HTTP Routing перехватывает мое исключение?
Учитывая этот код
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, я не понимаю, зачем мне это нужно. Мой код должен поймать его и вернуть complete(cause.response)
вместо. Как Akka HTTP перехватывает исключение до того, как мой код делает?
1 ответ
Согласно моему пониманию, это происходит потому, что leaderboardCreate
на самом деле не выполняется синхронно с complete
звоните, как вы могли ожидать. complete
метод возвращает StandardRoute
который простирается от Route
определяется как:
type Route = RequestContext ⇒ Future[RouteResult]
Другими словами, "маршрут" - это функция от контекста к Future
(из RouteResult
). И если вы посмотрите на complete
определение, это просто:
def complete(m: ⇒ ToResponseMarshallable): StandardRoute =
StandardRoute(_.complete(m))
Обратите внимание ⇒
до ToResponseMarshallable
, Это передача параметра по имени, который фактически превращает его в ленивую оценку.
Другими словами, все ваши try/catch
обертки очень маленький (и без исключения) код построения StandardRoute
это фиксирует вашу логику как ленивое значение, но не выполнение самой логики. Вот почему вам нужен пользовательский ExceptionHandler, который вы (или, скорее, Akka) действительно можете поместить в цепочку обработчиков ошибок для Future
когда он будет запущен.