mules-http4s - Http4s Caching Implementation Build Status 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.asynchttpclient.client._

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[IO] = (
//    = 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@705e39cc
// )

val exampleCached = AsyncHttpClient.resource[IO]().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[(Int, Int)] = Uncancelable(
//   body = cats.effect.IO$$$Lambda$12411/1112897921@698f0e11,
//   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: (Int, Int) = (1, 1)

val dadJokesRequest = Request[IO](Method.GET, uri"https://icanhazdadjoke.com/")
// dadJokesRequest: Request[IO] = (
//    = 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@16a7b866
// )

val exampleUnCached = AsyncHttpClient.resource[IO]().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[(Int, Int)] = Uncancelable(
//   body = cats.effect.IO$$$Lambda$12411/1112897921@17367327,
//   event = cats.effect.tracing.TracingEvent$StackTrace
// )

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