Skip to content

Instantly share code, notes, and snippets.

@adamw
Last active June 2, 2020 09:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save adamw/12fcda4602d45d24a0de02922c3d775c to your computer and use it in GitHub Desktop.
Save adamw/12fcda4602d45d24a0de02922c3d775c to your computer and use it in GitHub Desktop.
package sttp.tapir.examples
import cats.arrow.FunctionK
import cats.data.OptionT
import izumi.reflect.Tag
import org.http4s._
import org.http4s.server.Router
import org.http4s.server.blaze.BlazeServerBuilder
import org.http4s.syntax.kleisli._
import zio.interop.catz._
import zio.{Has, RIO, Runtime, ZIO, ZLayer}
import org.http4s.dsl.Http4sDsl
import zio.clock.Clock
import zio.random.Random
object ZioExampleHttp4sServer2 extends App {
type EffLocal[X] = RIO[Has[Int] with Has[String], X]
val dsl = Http4sDsl[EffLocal]
import dsl._
def logic(name: String): EffLocal[String] =
for {
v1 <- RIO.access[Has[Int]](_.get)
v2 <- RIO.access[Has[String]](_.get)
} yield s"Hello, $name ($v1, $v2)."
val service: HttpRoutes[EffLocal] = HttpRoutes.of[EffLocal] {
case GET -> Root / "hello" / name => Ok(logic(name))
}
type EffEnv = Random with Clock with Has[Int] with Has[String]
type Eff[X] = RIO[EffEnv, X]
val serviceAll: ZIO[Random with Clock, Nothing, HttpRoutes[Eff]] =
Translate[Random with Clock, Has[Int] with Has[String]](service)
val program: Eff[Unit] = ZIO.runtime[EffEnv].flatMap { implicit runtime =>
serviceAll.flatMap { sa =>
BlazeServerBuilder[Eff](runtime.platform.executor.asEC)(taskEffectInstance[EffEnv], zioTimer)
.bindHttp(8080, "localhost")
.withHttpApp(Router("/" -> sa).orNotFound)
.serve
.compile
.drain
}
}
Runtime.default.unsafeRun(program.provideLayer(Random.live ++ Clock.live ++ ZLayer.succeed(42) ++ ZLayer.succeed("x")))
}
object Translate {
def apply[R0 <: Has[_], R1 <: Has[_]: Tag](
baseService: HttpRoutes[RIO[R1, *]]
): ZIO[R0, Nothing, HttpRoutes[RIO[R0 with R1, *]]] = {
type Eff1[X] = RIO[R1, X]
type Eff2[X] = RIO[R0 with R1, X]
val eff1ToEff2 = new FunctionK[Eff1, Eff2] {
override def apply[A](fa: Eff1[A]): Eff2[A] = fa
}
def eff2ToEff1(r0: R0) =
new FunctionK[Eff2, Eff1] {
override def apply[A](fa: Eff2[A]): Eff1[A] = fa.provideSome[R1](r0.union[R1](_))
}
ZIO.access[R0] { r0 =>
baseService
.mapK(new FunctionK[OptionT[Eff1, *], OptionT[Eff2, *]] {
override def apply[A](fa: OptionT[Eff1, A]): OptionT[Eff2, A] = fa.mapK(eff1ToEff2)
})
.dimap[Request[Eff2], Response[Eff2]](_.mapK(eff2ToEff1(r0)))(_.mapK(eff1ToEff2))
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment