mules-http4s - Http4s Caching Implementation
Quick Start
To use mules-http4s in an existing SBT project with Scala 2.11 or a later version, add the following dependencies to your
build.sbt
depending on your needs:
libraryDependencies ++= Seq(
"io.chrisdavenport" %% "mules-http4s" % "<version>"
)
Basic Use
import cats._
import cats.implicits._
import cats.effect._
import io.chrisdavenport.mules._
import io.chrisdavenport.mules.caffeine._
import io.chrisdavenport.mules.http4s._
import org.http4s._
import org.http4s.implicits._
import org.http4s.client.Client
import org.http4s.ember.client.EmberClientBuilder
def testMiddleware[F[_]: Concurrent](c: Client[F], ref: Ref[F, Int]): Client[F] = {
Client{req => c.run(req).evalMap(resp => ref.update(_ + 1).as(resp))}
}
val jQueryRequest = Request[IO](Method.GET, uri"https://code.jquery.com/jquery-3.4.1.slim.min.js")
// jQueryRequest: Request[[A >: Nothing <: Any] => IO[A]] = (
// = GET,
// = Uri(
// scheme = Some(value = Scheme(https)),
// authority = Some(
// value = Authority(
// userInfo = None,
// host = RegName(host = code.jquery.com),
// port = None
// )
// ),
// path = /jquery-3.4.1.slim.min.js,
// query = ,
// fragment = None
// ),
// = HttpVersion(major = 1, minor = 1),
// = Headers(),
// = Stream(..),
// = org.typelevel.vault.Vault@7662cebd
// )
val exampleCached = EmberClientBuilder.default[IO].build.use{ client =>
for {
cache <- CaffeineCache.build[IO, (Method, Uri), CacheItem](None, None, 10000L.some)
counter <- Ref[IO].of(0)
cacheMiddleware = CacheMiddleware.client(cache, CacheType.Public)
finalClient = cacheMiddleware(testMiddleware(client, counter))
_ <- finalClient.run(jQueryRequest).use(_.as[String])
count1 <- counter.get
_ <- finalClient.run(jQueryRequest).use(_.as[String])
count2 <- counter.get
} yield (count1, count2)
}
// exampleCached: IO[Tuple2[Int, Int]] = FlatMap(
// ioe = Attempt(
// ioa = Map(
// ioe = Blocking(
// hint = Blocking,
// thunk = fs2.io.net.tls.TLSContextCompanionPlatform$BuilderCompanionPlatform$AsyncBuilder$$Lambda$12570/0x00000008033a0440@72b94e70,
// event = cats.effect.tracing.TracingEvent$StackTrace
// ),
// f = fs2.io.net.tls.TLSContextCompanionPlatform$BuilderCompanionPlatform$AsyncBuilder$$Lambda$12572/0x00000008033a2040@1aed8e3c,
// event = cats.effect.tracing.TracingEvent$StackTrace
// )
// ),
// f = cats.effect.kernel.Resource$$Lambda$12577/0x00000008033a6040@7a9abcfa,
// event = cats.effect.tracing.TracingEvent$StackTrace
// )
import cats.effect.unsafe.implicits.global // DON'T DO THIS IN PROD // DON'T DO THIS IN PROD
exampleCached.unsafeRunSync()
// res0: Tuple2[Int, Int] = (1, 1)
val dadJokesRequest = Request[IO](Method.GET, uri"https://icanhazdadjoke.com/")
// dadJokesRequest: Request[[A >: Nothing <: Any] => IO[A]] = (
// = GET,
// = Uri(
// scheme = Some(value = Scheme(https)),
// authority = Some(
// value = Authority(
// userInfo = None,
// host = RegName(host = icanhazdadjoke.com),
// port = None
// )
// ),
// path = /,
// query = ,
// fragment = None
// ),
// = HttpVersion(major = 1, minor = 1),
// = Headers(),
// = Stream(..),
// = org.typelevel.vault.Vault@719e680c
// )
val exampleUnCached = EmberClientBuilder.default[IO].build.use{ client =>
for {
cache <- CaffeineCache.build[IO, (Method, Uri), CacheItem](None, None, 10000L.some)
counter <- Ref[IO].of(0)
cacheMiddleware = CacheMiddleware.client(cache, CacheType.Public)
finalClient = cacheMiddleware(testMiddleware(client, counter))
_ <- finalClient.run(dadJokesRequest).use(_.as[String])
count1 <- counter.get
_ <- finalClient.run(dadJokesRequest).use(_.as[String])
count2 <- counter.get
} yield (count1, count2)
}
// exampleUnCached: IO[Tuple2[Int, Int]] = FlatMap(
// ioe = Attempt(
// ioa = Map(
// ioe = Blocking(
// hint = Blocking,
// thunk = fs2.io.net.tls.TLSContextCompanionPlatform$BuilderCompanionPlatform$AsyncBuilder$$Lambda$12570/0x00000008033a0440@72b94e70,
// event = cats.effect.tracing.TracingEvent$StackTrace
// ),
// f = fs2.io.net.tls.TLSContextCompanionPlatform$BuilderCompanionPlatform$AsyncBuilder$$Lambda$12572/0x00000008033a2040@5a74133e,
// event = cats.effect.tracing.TracingEvent$StackTrace
// )
// ),
// f = cats.effect.kernel.Resource$$Lambda$12577/0x00000008033a6040@506cf910,
// event = cats.effect.tracing.TracingEvent$StackTrace
// )
exampleUnCached.unsafeRunSync()
// res1: Tuple2[Int, Int] = (1, 2)