package code
package lib
import model._
import net.liftweb._
import common._
import http._
import rest._
import json._
import scala.xml._
/**
* A simple example of a REST style interface
* using the basic Lift tools
*/
object BasicWithHelper extends RestHelper {
/*
* Serve the URL, but have a helpful error message when you
* return a 404 if the item is not found
*/
serve {
case "simple3" :: "item" :: itemId :: Nil JsonGet _ =>
for {
// find the item, and if it's not found,
// return a nice message for the 404
item <- Item.find(itemId) ?~ "Item Not Found"
} yield item: JValue
case "simple3" :: "item" :: itemId :: Nil XmlGet _ =>
for {
item <- Item.find(itemId) ?~ "Item Not Found"
} yield item: Node
}
serve {
// Prefix notation
case JsonGet("simple4" :: "item" :: Item(item) :: Nil, _) =>
// no need to explicitly create a LiftResponse
// Just make it JSON and RestHelper does the rest
item: JValue
// infix notation
case "simple4" :: "item" :: Item(item) :: Nil XmlGet _ =>
item: Node
}
// serve a bunch of items given a single prefix
serve ( "simple5" / "item" prefix {
// all the inventory
case Nil JsonGet _ => Item.inventoryItems: JValue
case Nil XmlGet _ => Item.inventoryItems: Node
// a particular item
case Item(item) :: Nil JsonGet _ => item: JValue
case Item(item) :: Nil XmlGet _ => item: Node
})
/**
* Here's how we convert from an Item
* to JSON or XML depending on the request's
* Accepts header
*/
implicit def itemToResponseByAccepts: JxCvtPF[Item] = {
case (JsonSelect, c, _) => c: JValue
case (XmlSelect, c, _) => c: Node
}
/**
* serve the response by returning an item
* (or a Box[Item]) and let RestHelper determine
* the conversion to a LiftResponse using
* the itemToResponseByAccepts partial function
*/
serveJx[Item] {
case "simple6" :: "item" :: Item(item) :: Nil Get _ => item
case "simple6" :: "item" :: "other" :: item :: Nil Get _ =>
Item.find(item) ?~ "The item you're looking for isn't here"
}
/**
* Same as the serveJx example above, but we've
* used prefixJx to avoid having to copy the path
* prefix over and over again
*/
serveJx[Item] {
"simple7" / "item" prefixJx {
case Item(item) :: Nil Get _ => item
case "other" :: item :: Nil Get _ =>
Item.find(item) ?~ "The item you're looking for isn't here"
}
}
}
/**
* A simple example of a REST style interface
* using the basic Lift tools
*/
object BasicWithHelper extends RestHelper {
LiftRules.statelessDispatchTable.append(BasicWithHelper)
serve {
case "simple3" :: "item" :: itemId :: Nil JsonGet _ =>
for {
// find the item, and if it’s not found,
// return a nice message for the 404
item <- Item.find(itemId) ?~ "Item Not Found"
} yield item: JValue
case "simple3" :: "item" :: itemId :: Nil XmlGet _ =>
for {
item <- Item.find(itemId) ?~ "Item Not Found"
} yield item: Node
}
case "simple3" :: "item" :: itemId :: Nil JsonGet _ =>
for {
// find the item, and if it’s not found,
// return a nice message for the 404
item <- Item.find(itemId) ?~ "Item Not Found"
} yield item: JValue
dpp@raptor:~/proj/simply_lift/samples/http_rest$ curl http://localhost:8080/simple3/item/12999
Item Not Found
dpp@raptor:~/proj/simply_lift/samples/http_rest$ curl http://localhost:8080/simple3/item/1234
{
"id":"1234",
"name":"Cat Food",
"description":"Yummy, tasty cat food",
"price":4.25,
"taxable":true,
"weightInGrams":1000,
"qnty":4
}
case "simple3" :: "item" :: itemId :: Nil XmlGet _ =>
for {
item <- Item.find(itemId) ?~ "Item Not Found"
} yield item: Node
dpp@raptor:~/proj/simply_lift/samples/http_rest$ curl -i -H "Accept: application/xml" http://localhost:8080/simple3/item/1234 HTTP/1.1 200 OK Expires: Wed, 9 Mar 2011 01:48:38 UTC Content-Length: 230 Cache-Control: no-cache; private; no-store Content-Type: text/xml; charset=utf-8 Pragma: no-cache Date: Wed, 9 Mar 2011 01:48:38 UTC X-Lift-Version: Unknown Lift Version Server: Jetty(6.1.22) <?xml version="1.0" encoding="UTF-8"?> <item> <id>1234</id> <name>Cat Food</name> <description>Yummy, tasty cat food</description> <price>4.25</price> <taxable>true</taxable> <weightInGrams>1000</weightInGrams> <qnty>4</qnty> </item>
/**
* Convert an item to XML
*/
implicit def toXml(item: Item): Node =
<item>{Xml.toXml(item)}</item>
/**
* Convert the item to JSON format. This is
* implicit and in the companion object, so
* an Item can be returned easily from a JSON call
*/
implicit def toJson(item: Item): JValue =
Extraction.decompose(item)
serve {
// Prefix notation
case JsonGet("simple4" :: "item" :: Item(item) :: Nil, _) =>
// no need to explicitly create a LiftResponse
// Just make it JSON and RestHelper does the rest
item: JValue
// infix notation
case "simple4" :: "item" :: Item(item) :: Nil XmlGet _ =>
item: Node
}
// serve a bunch of items given a single prefix
serve ( "simple5" / "item" prefix {
// all the inventory
case Nil JsonGet _ => Item.inventoryItems: JValue
case Nil XmlGet _ => Item.inventoryItems: Node
// a particular item
case Item(item) :: Nil JsonGet _ => item: JValue
case Item(item) :: Nil XmlGet _ => item: Node
})
dpp@raptor:~/proj/simply_lift/samples/http_rest$ curl http://localhost:8080/simple5/item
[{
"id":"1234",
"name":"Cat Food",
"description":"Yummy, tasty cat food",
"price":4.25,
"taxable":true,
"weightInGrams":1000,
"qnty":4
},
...
,{
"id":"1237",
"name":"Sloth Food",
"description":"Slow, slow sloth food",
"price":18.33,
"taxable":true,
"weightInGrams":750,
"qnty":62
}]
dpp@raptor:~/proj/simply_lift/samples/http_rest$ curl http://localhost:8080/simple5/item/1237
{
"id":"1237",
"name":"Sloth Food",
"description":"Slow, slow sloth food",
"price":18.33,
"taxable":true,
"weightInGrams":750,
"qnty":62
}
implicit def itemToResponseByAccepts: JxCvtPF[Item] = {
case (JsonSelect, c, _) => c: JValue
case (XmlSelect, c, _) => c: Node
}
serveJx[Item] {
case "simple6" :: "item" :: Item(item) :: Nil Get _ => item
case "simple6" :: "item" :: "other" :: item :: Nil Get _ =>
Item.find(item) ?~ "The item you’re looking for isn’t here"
}
dpp@raptor:~/proj/simply_lift/samples/http_rest$ curl http://localhost:8080/simple6/item/1237
{
"id":"1237",
"name":"Sloth Food",
"description":"Slow, slow sloth food",
"price":18.33,
"taxable":true,
"weightInGrams":750,
"qnty":62
}
dpp@raptor:~/proj/simply_lift/samples/http_rest$ curl -H "Accept: application/xml" http://localhost:8080/simple6/item/1234
<?xml version="1.0" encoding="UTF-8"?>
<item>
<id>1234</id>
<name>Cat Food</name>
<description>Yummy, tasty cat food</description>
<price>4.25</price>
<taxable>true</taxable>
<weightInGrams>1000</weightInGrams>
<qnty>4</qnty>
</item>
serveJx[Item] {
"simple7" / "item" prefixJx {
case Item(item) :: Nil Get _ => item
case "other" :: item :: Nil Get _ =>
Item.find(item) ?~ "The item you’re looking for isn’t here"
}
}
(C) 2012 David Pollak