mules-http4s - Http4s Caching Implementation Maven Central

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(Scheme(https)),
//     authority = Some(
//       Authority(userInfo = None, host = RegName(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@3bb2b0a9
// )

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 = Pure(()),
//   f = cats.effect.kernel.Resource$$Lambda$12565/0x0000000803353840@284dd1fd,
//   event = cats.effect.tracing.TracingEvent$StackTrace
// )

import cats.effect.unsafe.implicits.global // 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(Scheme(https)),
//     authority = Some(
//       Authority(
//         userInfo = None,
//         host = RegName(icanhazdadjoke.com),
//         port = None
//       )
//     ),
//     path = /,
//     query = ,
//     fragment = None
//   ),
//   `` = HttpVersion(major = 1, minor = 1),
//   `` = Headers(),
//   `` = Stream(..),
//   `` = org.typelevel.vault.Vault@75dd5f46
// )

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 = Pure(()),
//   f = cats.effect.kernel.Resource$$Lambda$12565/0x0000000803353840@5b448eac,
//   event = cats.effect.tracing.TracingEvent$StackTrace
// )

exampleUnCached.unsafeRunSync()
// res1: Tuple2[Int, Int] = (1, 2)