Skip to content

Instantly share code, notes, and snippets.

@ssuravarapu
Created January 11, 2011 16:19
Show Gist options
  • Save ssuravarapu/774649 to your computer and use it in GitHub Desktop.
Save ssuravarapu/774649 to your computer and use it in GitHub Desktop.
case r @ Req("webservices" :: "product" :: id :: _, _, PutRequest) => {
def updateResource(id: String, r: Req): LiftResponse = {
val reqETag = r.header("If-Match") openOr ""
val product = Product.findByKey(id.toLong)
product match {
case Full(x) => {
compareETags(reqETag, x.updatedAt.toLong.toString) match {
case true => {
save(r.xml.open_!, x)
NoContentResponse(x.updatedAt.toLong.toString)
}
case false => PreConditionFailedResponse(x.updatedAt.toLong.toString,
"Update failed. Resource state changed.")
}
}
case _ => NotFoundResponse("Resource not found")
}
}
r.xml_? match {
case true => updateResource(id, r)
case false => NotFoundResponse("Resource not found")
}
}
case class NoContentResponse(eTag: String) extends LiftResponse with HeaderDefaults {
def toResponse = InMemoryResponse(Array(), "ETag" -> ("\"" + eTag + "\"") :: headers, cookies, 204)
}
case class PreConditionFailedResponse(eTag: String, msg: String) extends LiftResponse with HeaderDefaults {
def toResponse = InMemoryResponse(msg.getBytes("UTF-8"), "ETag" -> ("\"" + eTag + "\"") :: headers, cookies, 412)
}
case class NotModifiedResponse(eTag: String) extends LiftResponse with HeaderDefaults {
def toResponse = InMemoryResponse(Array(), "ETag" -> ("\"" + eTag + "\"") :: headers, cookies, 304)
}
package code.model
import net.liftweb.mapper._
class Product extends LongKeyedMapper[Product] with CreatedUpdated {
def getSingleton = Product
def primaryKeyField = itemNumber
object itemNumber extends MappedLongIndex(this)
object name extends MappedString(this, 20)
object price extends MappedDouble(this)
object quantity extends MappedInt(this)
}
object Product extends Product with LongKeyedMetaMapper[Product]
object WebService extends RestHelper {
serve {
case r @ Req("webservices" :: "product" :: id :: _, _, GetRequest) => {
val reqETag = r.header("If-None-Match") openOr ""
val product = Product.findByKey(id.toLong)
product match {
case Full(x) => {
val resourceETag = x.updatedAt.toLong.toString
compareETags(reqETag, resourceETag) match {
case true => NotModifiedResponse(resourceETag)
case false => XmlResponse(toXml(x), resourceETag)
}
}
case _ => NotFoundResponse("Resource not found")
}
}
}
def compareETags(reqETags: String, respETag: String) = reqETags split(",") map (_.trim) contains("\"" + respETag + "\"")
}
class XmlResponse(val xml: Node, val code: Int, val mime: String, val _headers: List[(String, String)],
val cookies: List[HTTPCookie]) extends NodeResponse {
def docType = Empty
def out: Node = xml
def headers = _headers
}
object XmlResponse {
def apply(xml: Node, eTag: String) =
new XmlResponse(xml, 200, "application/xml", ("Content-Type" -> "application/xml") :: "ETag" -> ("\"" + eTag + "\"") :: Nil, Nil)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment