Last Updated: December 31, 2020
·
3.978K
· brianhsu

[Lift Web Framework] Minimal REST API Example

RestHelper

=============

RestHelper is a trait provided by Lift web framework, which let us create Rest API in a simple and beautiful way.

There are already lots of example of RestHelper, but I feel most of those example a little bit long, so I've created a really minimal Json REST API of a Blog article, which support GET / POST and DELETE request.

Blog Model

Since we need support POST and DELETE, so we need a simple model object to simulate persistence layer.

Here is the code for Model, if you're familiar with Scala, it should be quite easy to understand.

case class Article(id: Int, title: String, content: String) {
  def toJSON = {
    import net.liftweb.json._
    import net.liftweb.json.JsonDSL._

    ("id" -> id) ~ ("title" -> title) ~ ("content" -> content)
  } 
}

object Article {

  var store: List[Article] = Article(12, "qqq", "sss") :: Nil

  def addArticle(title: String, content: String): Article = {
    val nextID = store.map(_.id).max + 1
    val newArticle = new Article(nextID, title, content)
    store ::= newArticle
    newArticle
  }

  def getArticle(id: Int): Option[Article] = store.filter(_.id == id).headOption
  def deleteArticle(id: Int) { store = store.filterNot(_.id == id) }
}

Blog API REST Helper

========================

Next we need to implement RestHelper trait.

The most important part of the following code is serve, which leverage the Partial Function / Pattern Matching to determine if we accept this request, which type of reqeust it is, and redirect to the corresponding method.

import net.liftweb.http.rest.RestHelper
import net.liftweb.http.OkResponse
import net.liftweb.util.Helpers.AsInt

object BlogAPI extends RestHelper {

  def getArticleJSON(postID: Int): Option[JValue] = {
    Article.getArticle(postID).map(_.toJSON)
  }

  def deleteArticle(postID: Int) = {
    Article.deleteArticle(postID)
    new OkResponse
  }

  def postArticle(jsonData: JValue): JValue = {
    Article.addArticle(
      title = (jsonData \ "title").extract[String],
      content = (jsonData \ "content").extract[String]
    ).toJSON
  }

  serve {
    case "api" :: "blog" :: AsInt(postID) :: Nil JsonGet req => getArticleJSON(postID)
    case "api" :: "blog" :: AsInt(postID) :: Nil JsonDelete req => deleteArticle(postID)
    case "api" :: "blog" :: Nil JsonPost ((jsonData, req)) => postArticle(jsonData)
  }
}

Boot.scala

==============

Finally, we need to append BlogAPI to Lift's dispatch table in Boot.scala.

class Boot
{
  def boot
  {
    LiftRules.dispatch.append(BlogAPI)
  }
}