Skip to content

Instantly share code, notes, and snippets.

@hoffrocket
Created April 28, 2011 18:23
Show Gist options
  • Save hoffrocket/946936 to your computer and use it in GitHub Desktop.
Save hoffrocket/946936 to your computer and use it in GitHub Desktop.
// Copyright 2011 Foursquare Labs Inc. All Rights Reserved.
package com.foursquare.snippet
import com.foursquare.lib._
import net.liftweb.common._
import net.liftweb.http._
import net.liftweb.util._
import net.liftweb.util.Helpers._
import scala.xml._
object FSResourceRewriter {
@volatile var hashCache: Map[String, String] = Map.empty
def attachResourceId(href: String): String = {
def pathCalc(name:String, hash: String) = {
if (Props.mode == Props.RunModes.Development) {
name + "?" + hash + "=_"
} else {
s3ResourcePath(name, hash)
}
}
def hash(name:String) = hashCache.get(name) match {
case Some(hash) => hash
case None =>
val hash = LiftRules.doWithResource(name)(is =>{
StaticResources.md5hash(is)
}).openOr(Helpers.nextFuncName)
hashCache += (name->hash)
hash
}
if (!href.startsWith("http")){
pathCalc(href, hash(href))
} else {
href
}
}
def s3ResourcePath(name: String, hash: String) = {
val protocol = if (S.request.exists(IpHelpers.isHttps(_))) "https" else "http"
protocol + "://4sqstatic.s3.amazonaws.com" + StaticResources.nameHash(name, hash)._1
}
}
class FSResourceRewriter extends RenderSnippet {
def render(xhtml: NodeSeq): NodeSeq = logTime("FSResourceRewriter"){
replaceElements(xhtml)
}
def replaceElements(xhtml: NodeSeq): NodeSeq = {
xhtml flatMap (_ match {
case e @ Elem(prefix, "link", attrs, scope, childs @ _*) =>
attrStr(attrs, "href").map ( href =>
Elem(prefix, "link",
MetaData.update(attrs,
scope,
new UnprefixedAttribute("href", FSResourceRewriter.attachResourceId(href), Null)),
scope, childs: _*)) openOr e
case e @ Elem(prefix, "script", attrs, scope, childs @ _*) =>
attrStr(attrs, "src") map (src =>
Elem(prefix, "script",
MetaData.update(attrs,
scope,
new UnprefixedAttribute("src", FSResourceRewriter.attachResourceId(src), Null)),
scope, childs: _*)) openOr e
case e @ Elem(prefix, "img", attrs, scope, childs @ _*) =>
attrStr(attrs, "src") map (src =>
Elem(prefix, "img",
MetaData.update(attrs,
scope,
new UnprefixedAttribute("src", FSResourceRewriter.attachResourceId(src), Null)),
scope, childs: _*)) openOr e
case e @ Elem(prefix, name, attrs, scope, childs @ _*) if !childs.isEmpty => Elem(prefix, name, attrs, scope, childs flatMap replaceElements :_*)
case e => e
})
}
private def attrStr(attrs: MetaData, attr: String): Box[String] = attrs.get(attr) match {
case None => Empty
case Some(Nil) => Empty
case Some(x) => Full(x.toString)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment