I have to admit I am far from expert in Scala, that's why when recently I had to prototype an API in this language, I shuddered. Frameworks like Akka HTTP or HTTP4S were far too complex for a novice in the field like me, because learning Scala is not about the syntax, but about the mindset. And it's only logical that someone coming from the field of totally different languages such as Python or Javascript, can have a little trouble understanding concepts like the actor model or the functional proper way of using HTTP4S.

The original Actor Model

Actor model in action


That's why I welcomed the discovery of Cask, a micro HTTP framework which tries to follow closely the footsteps of Flask for Python. This looked like a good compromise between not switching straight away to Akka/Http4s, but still enjoying the benefits of a strongly typed language as interesting as Scala.

Example of Cask usage for an API endpoint from a Postgres database

Setting up:

The author recommends to use his own build tool called Mill. Even though I found it easy to understand, I decided to stick with SBT out of habit, since that is what I had used in the past.

Dependencies for this project:

libraryDependencies ++= Seq("com.lihaoyi" %% "cask" % "0.2.9",
  "com.lihaoyi" %% "utest" % "0.7.4" % Test,
  "com.lihaoyi" %% "requests" % "0.5.1",
  "org.postgresql" % "postgresql" % "42.2.8",
  "ch.qos.logback" % "logback-classic" % "1.2.3",
  "io.getquill" %% "quill-jdbc" % "3.2.0",
  "com.typesafe.scala-logging" %% "scala-logging" % "3.9.2",
  "com.typesafe" % "config" % "1.4.0")

What are we retrieving in the API

This is an API which retrieves information about movies showing in the local cinemas of my city, so the modeled data is basically a movie. We create a case class, because that is what will be used by Quill to map to the values in the Postgres table and be able to retrieve the data. So when I do:

case class Movies(
                   cinema: String,
                   details: String,
                   title: String,
                   movie_date: String,
                   movie_time: String

with this I actually mean that there is a table with the name movies that has as fields each of the case class fields. By the way! I am aware that certain data types are not correct. Date and time should not be strings. However, this is for the moment done like this to deal with data in a database that has been scraped and does not conform to proper date format yet. Work in progress!

How to manage all the connection settings for the DB

As simple as creating an application.properties file in your resources folder with the following content


Of course, take the necessary precautions when dealing with version control and this file.

So where is my easy API?

There you go. We do this via defining a route for movies with a function which creates a context to run the database query. See the Quill documentation for more details, but in this example we are basically doing a SELECT * from movies , so it couldn't get easier.

object moviescrape extends cask.MainRoutes with LazyLogging {
  override def port: Int = 8081
  lazy val ctx = new PostgresJdbcContext(SnakeCase, "ctx")
  import ctx._
  def getMovies() = {
    val content = ctx.run(query[Movies])
      .map(m => {ujson.Obj("cinema" -> ujson.Str(m.cinema),
        "details" -> ujson.Str(m.details), "title" -> ujson.Str(m.title),
        "movie_date" -> ujson.Str(m.movie_date),
        "movie_time" -> ujson.Str(m.movie_time))})

    upickle.default.write(ujson.Obj("data" -> content))


Things might get a bit tricky around the part of returning the proper json with the response. I tried a few different tools, such as Circe and the author's own Ujson and at the end I settled with the latter.

But... will it scale?

I don't think this library is meant to handle your super scalable APIs for deployments that need to bear a load of millions of users, but if you are ever in the need of playing around with API development in Scala in order to understand the language a little better, Cask will definitely help you to get your feet wet without the headaches of jumping straight into Akka HTTP.


This post is also available on DEV.