使用 rho 在 http4s 中添加异常处理

Add exception handling in http4s with 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))
   }
} 

这样我可以确保无论我 return,它总是 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 不是一个响应(我可以调用 .pure 对它们进行类型检查) 但是代码会编译,但我得到这个异常:

Cannot convert from fs2.Task[Product with Serializable] to an Entity, because no EntityEncoder[fs2.Task[Product with Serializable]] instance could be found. Ok(dao.readAll.map(_.asJson)).handleWith(errorHandler)

2。为每个 RhoRoute

添加错误处理程序

定义 rhoRoute 后,我想映射它并将错误处理程序添加到每条路线,所以在 r 做一些让我在某处添加 'handleWith' 的事情(下面将不起作用)

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

如果我不能让它工作,我可能会回到默认的 dsl,但我真的很喜欢 rho

所以第 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 部分。欢迎所有帮助:-)