Try Unfiltered
It’s not hard to write a request handler in the Scala console using Unfiltered. The tricky part is getting everything on the classpath.
Play Project
The approach recommended here uses giter8, a tool for setting up projects based on templates stored in github. Assuming you don’t have giter8 installed and you are on a network-connected Linux or Mac, it’s easy to fix that.
curl https://raw.githubusercontent.com/foundweekends/conscript/master/setup.sh | sh
That is conscript. Its setup.sh
places a permanent (assuming you don’t delete it) executable script in ~/bin/cs
. At some point you may want to add ~/bin
to your executable search path, but these instructions will not assume it is.
~/bin/cs foundweekends/giter8
That installs a g8
. Now you have a script to run giter8. The next step creates a sbt project under the current working directory.
~/bin/g8 unfiltered/unfiltered --name=justplayin
Okay, finally we can use this project with sbt to get a console for Unfiltered. You do have sbt setup, don’t you?
cd justplayin
sbt console
Consoled
Now that you have a scala>
prompt with the unfiltered-filter
and unfiltered-jetty
modules on the classpath, let’s have some fun.
sourceimport unfiltered.request._
import unfiltered.response._
val echo = unfiltered.filter.Planify {
case Path(Seg(p :: Nil)) => ResponseString(p)
}
This filter echo
would work with any servlet container. We can use it in a Jetty server right now.
sourceunfiltered.jetty.Server.anylocal.plan(echo).run()
The startup message tells you which open port was selected, and by default it is only listening to requests from 127.0.0.1. So on the same machine, you can make requests to your server. e.g.
curl http://127.0.0.1:<the right port>/hello+world
Fancy desktop web browsers will work too. Notice that exactly one path segment is required for the filter to respond to the request. If you ask for the root path or a deeper path, the echo
filter will not handle the request and Jetty responds with a 404 page.
If we want to handle any request, we could broaden the pattern matching expression. (Press enter to stop the running server.)
sourceval echoNice = unfiltered.filter.Planify {
case Path(Seg(p :: Nil)) => ResponseString(p)
case _ => ResponseString(
"I can echo exactly one path element."
)
}
unfiltered.jetty.Server.anylocal.plan(echoNice).run()
Or we could define another filter chain it to the first.
sourceval nice = unfiltered.filter.Planify {
case _ => ResponseString(
"I can echo exactly one path element."
)
}
unfiltered.jetty.Server.anylocal.plan(echo).plan(nice).run()
Happy now?