使用 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 部分。欢迎所有帮助:-)
我正在使用 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 部分。欢迎所有帮助:-)