package controllers.caching import play.api.mvc.Results.NotModified import play.api.mvc.{Request, Result} import scala.concurrent.{ExecutionContext, Future} trait Etagable[A]: extension (a: A) def etag: String extension [A, R[X] <: Request[X], E: Etagable](request: R[A]) { def checkFreshAsync(entity: E)(onStale: => Future[Result])(using ec: ExecutionContext): Future[Result] = { compareEtag(entity).fold(onStale)( etag => Future.successful(NotModified.withHeaders("ETag" -> etag)) ) } def checkFresh(entity: E)(onStale: => Result): Result = { compareEtag(entity).fold(onStale)( etag => NotModified.withHeaders("ETag" -> etag) ) } private def compareEtag(entity: E) = request.headers.get("If-None-Match").filter(e => e == entity.etag) }