Scala, ZIO, Tapir - zio-http and tapir, how to create rejection/error handler on API side?

Viewed 33

I have a weird problem with error middleweare or I'm using it in wrong way. I would like to add error middleware to my tapir routes and catch all errors from "inside" application. I have simple tapir route:

object SomeApi{
 
   val zServerLogic = SomeTapirEndpoint.someRoute.zServerLogic(_ => ZIO.succeed(MyEmptyResponse))
 
   def myApiRoutes: HttpApp[Any, Throwable] =
     ZioHttpInterpreter().toHttp(
       zServerLogic
     )
 }

I also added it to server when it starts:

_ <- Server
   .start(
     port = config.port,
     http = myapis @@ ErrorMiddleware.errorMiddleware
   )
   .exitCode

Error middleware looks like below:

object ErrorMiddleware {
   val errorMiddleware = new HttpMiddleware[Any, Throwable] {
     override def apply[R1 <: Any, E1 >: Throwable](
       http: HttpApp[R1, E1]
     ) =
       http.catchAll { ex =>
         val errorResponse: ZIO[Any, IOException, MyResponse] = for {
           _ <- ZIO.logError(s"Logic failed: ${ex.toString}")
         } yield MyResponse("FAIL")
         ZIO.succeed(errorResponse)
       }
   }
 }

My questions are:

  1. How I could return my custom response instead of one from zhttp.http?
  2. How could I catch all errors from tapir routes - it looks like tapir catch all errors in zServerLogic and catch all exceptions there and return just Either, so my error middleware always return right side. How could I fix this to catch all errors from application? For example when I put wrong endpoint url or something bad happened during processing logic?

Is it possible to create something similar to Akka's rejection handler to handle all errors on API side? Or maybe there is other solution?

0 Answers
Related