Добавьте обработку исключений в http4s с помощью rho

Я использую http4s & rho (в основном для интеграции Swagger)

Мои сервисы используют этот объект DAO, методы, которые могут генерировать исключения (Task)

case class BasicMatchDao() {
 def readAll(): Task[List[BasicMatch]] = Task.fail(ActionNotImplemented("readAll")) 
 def read(id: String): Task[Option[BasicMatch]] = readQuery(id).option.transact(xa)
}

В моем RhoService я могу справиться с такими как

private def exceptionToJson(t: Throwable):Json = Json.obj("error" -> t.getMessage.asJson)

val rhoService = new RhoService {
   GET / path |>> { (request: Request) =>
     Ok(dao.readAll.map(_.asJson)).handleWith {
        case t:ActionNotImplemented => NotImplemented(exceptionToJson(t))
        case t:Throwable => InternalServerError(exceptionToJson(t))
   }
} 

Таким образом, я уверен, что все, что я вернусь, это всегда Json

Так как я не хочу загрязнять каждый RhoRoute подобной обработкой ошибок, я хочу сделать что-то, что возможно со стандартным http4s.dsl, но я не могу работать с rho:

1. Создайте обработчик ошибок по умолчанию

например добавить

 ...
 Ok(dao.readAll.map(_.asJson)).handleWith(errorHandler)
 ...

private def errorHandler(): PartialFunction[Throwable, Task[Response]] = {
      case t:ActionNotImplemented => NotImplemented(exceptionToJson(t))
      case t:Throwable => InternalServerError(exceptionToJson(t))
}

Это не удастся, потому что NotImplemented не является Response (я могу вызвать.pure для них, чтобы заставить проверку типов работать) Но тогда код скомпилируется, но я получаю это исключение:

Невозможно преобразовать из fs2.Task[Product with Serializable] в Entity, поскольку не найден экземпляр EntityEncoder[fs2.Task[Product with Serializable]]. Ok(dao.readAll.map(_. AsJson)). HandleWith(ErrorHandler)

2. Добавьте обработчик ошибок к каждому RhoRoute

После определения rhoRoute я хотел бы отобразить его и добавить обработчик ошибок к каждому маршруту, поэтому сделайте что-то в r, что позволит мне добавить где-нибудь handleWith(ниже не будет работать)

 new RhoService(rhoService.getRoutes.map(_.handleWith(errorHandler))

Если я не могу заставить это работать, я, вероятно, вернусь к стандартному dsl, но мне действительно понравился rho

1 ответ

Решение

Итак, часть 1 исправлена. Определение задачи как Task[BaseResult] вместо Task[Response] буду работать

import org.http4s.rho.Result.BaseResult

val errorHandler: PartialFunction[Throwable, Task[BaseResult]] = {
    case t:ActionNotImplemented => NotImplemented(exceptionToJson(t))
    case t:Throwable => InternalServerError(exceptionToJson(t))
  }

Я смотрю на часть 2, а также. Любая помощь приветствуется:-)

Другие вопросы по тегам