scalascala-catsziohttp4s

How to compose an effect with an Http4s HttpRoutes?


I have an http4s HttpRoutes and a task in my effect type (ZIO, if that matters). The effect is side-effecting and returns no value. I want to compose the two together, creating a new HttpRoutes that will run the effect before any matching route in the HttpRoutes.

import zio.Task

val httpRoutes: HttpRoutes[Task] = ...
val effect: Task[Unit] = ...

val combined: HttpRoutes[Task] = ???

How do I combine the HttpRoutes and the effect together?


Solution

  • Naive implementation according to https://http4s.org/v0.21/middleware

    works for me

    @accessible
    trait HttpServer {
      def bindHttp: UIO[Server[Task]]
    }
    
    object HttpServer {
      def make(
        httpRoutes: HttpRoutes[Task],
        cpuPool: ExecutionContext@Id("zio.cpu"),
      ) = {
        for {
          implicit0(rts: Runtime[Any]) <- ZIO.runtime[Any].toManaged_
          combined = Kleisli { (req: Request[Task]) =>
            val effect: Task[Unit] = Task.effectTotal(println("123"))
            OptionT.liftF(effect).flatMap { _ =>
              httpRoutes(req)
            }
          }
          srv <- BlazeServerBuilder[Task](cpuPool)
            .withHttpApp(combined.orNotFound)
            .bindHttp(host = "0.0.0.0")
            .resource
            .toManaged
        } yield new HttpServer {
          val bindHttp = IO.succeed(srv)
        }
      }
    }