Created
January 21, 2012 19:30
-
-
Save m242/1653672 to your computer and use it in GitHub Desktop.
HTTP Cache for Action Results, Play Framework 2.0
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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