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 trait CheckFresh { protected def checkFreshAsync[A, E: Etagable](entity: E)(onStale: => Future[Result])(using request: Request[A], ec: ExecutionContext): Future[Result] = { compareEtag(request, entity).fold(onStale)( etag => Future.successful(NotModified.withHeaders("ETag" -> etag)) ) } protected def checkFresh[A, E: Etagable](entity: E)(onStale: => Result)(using request: Request[A]): Result = { compareEtag(request, entity).fold(onStale)( etag => NotModified.withHeaders("ETag" -> etag) ) } private def compareEtag[A, E: Etagable](request: Request[A], entity: E) = request.headers.get("If-None-Match").filter(e => e == entity.etag) }