Skip to content

Instantly share code, notes, and snippets.

@m242
Created January 21, 2012 19:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save m242/1653672 to your computer and use it in GitHub Desktop.
Save m242/1653672 to your computer and use it in GitHub Desktop.
HTTP Cache for Action Results, Play Framework 2.0
package controllers
import play.api._
import play.api.cache._
import play.api.libs._
import play.api.mvc._
import play.api.Play.current
trait HttpCache {
self:Controller =>
// Set http.cachetime in application.conf to determine cache ttl.
// Defaults to 120 seconds.
// Sample: http.cachetime=3600
val cacheTime = Play.configuration getInt "http.cachetime" getOrElse 120
val rfcFormat = {
val sdf = new java.text.SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z")
sdf setTimeZone { java.util.TimeZone getTimeZone "GMT" }
sdf
}
def HttpCache[A] (action: Action[A]): Action[A] = {
Action(action.parser) { request =>
val cacheKey = "url-" + request.host + request.uri
// Retrieve the Result from the cache or run the action
// if it doesn't exist, and set the appropriate Cache-Control
// and Last-Modified headers.
val (cachedResponse:Result, modTime:Double) = Cache get cacheKey getOrElse {
val date = new java.util.Date
val expires = new java.util.Date(date.getTime + cacheTime * 1000)
val response = action(request).asInstanceOf[SimpleResult[A]]
.withHeaders (CACHE_CONTROL -> { "public, max-age=" + cacheTime })
.withHeaders (LAST_MODIFIED -> { rfcFormat format date })
.withHeaders (EXPIRES -> { rfcFormat format expires })
val modTime:Double = math floor { date.getTime / 1000 }
Cache set (cacheKey, (response, modTime), cacheTime)
(response, modTime)
}
// Check for If-Modified-Since in the request and send a
// 304 response if the cached item hasn't changed, otherwise
// send the original Result.
request.headers get IF_MODIFIED_SINCE filter { dateStr =>
math.floor({ try {
rfcFormat parse dateStr
} catch {
case e => new java.util.Date(1)
}}.getTime / 1000) >= modTime
} map { _ => NotModified } getOrElse cachedResponse
}
}
}
// Add the HttpCache trait to the Controller.
object Application extends Controller with HttpCache {
def index = Action {
Ok(views.html.index("Your new application is ready."))
}
// An example of how to wrap the action with the HttpCache function.
def test = HttpCache {
Action {
Ok("Date: "+new java.util.Date)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment