http4s provides a minimal interface for creating a HTTP server using Scala. It tries to offer a typesafe and functional approach to building applications with HTTP. On top of that, a user may then choose from a number of backends on which their service can run (currently, the main options are Blaze and servlets).
The documentation for http4s is fairly light at the moment, so I hope to provide a series of posts here to go through the main features that will be needed for creating a full application with the service.
First, we will look at the setup of an initial skeleton application.
Set up a
build.sbt like this:
Then a basic skeleton for serving can look like:
BlazeBuilder is an object which provides a builder pattern for setting up a running
server which uses the Blaze (async IO) backend.
The code in
SkeletonServer binds to all interfaces on port 8080, sets up a service at the
/, starts the server, and waits until the server loop terminates.
When defining your service,
HttpService expects a partial function from
Task[Response]. That is, given a pattern match against the HTTP request on
the left-hand-side (which we will generally write using the http4s DSL), the
right-hand-side will return a
scalaz.concurrent.Task, which, when run, will
return the response.
Task in a Nutshell
If you haven’t come across
Task before, an initial intuition could be that it is
scala.concurrent.Future in that it can encompass the idea of
asynchronous computation. Some obvious differences in behaviour are that it does
no memoization of the result, and it only does the computation to calculate the
result on request. So at the point where a
Task is returned, no work has yet
been done to generate a response. This does not mean that we can’t write code which
depends on the result - for a start, its
flatMap methods allow the
response to be adapted.
The above code is enough to get a service running. The next step will be to
parse HTTP requests, in particular, query and path parameters. We will look in
more detail at
HttpService, and how the request pattern matching works.