Scala: how to embed a small web server into a scal

2020-06-15 05:38发布

问题:

For a little educational project intended as a community resource to help people learn Scala I am looking for a simple way to serve and process web pages in a background thread.

Minimal background: Scalatron is a multi-player game in which players pit bot programs (written in Scala) against each other. It is accompanied by a step-by-step Scala tutorial. Currently players need to use an IDE on their local machines to compile bots, which are then published into the game by copying them into a shared network directory. This is cumbersome. For the next version it would be nice to offer browser-based bot editing and publishing to maximally simplify the setup for both organizers and players.

I already got a background thread working that will compile Scala source code arriving on the server on the fly (obviating the need for a full IDE). Next I have to run a tiny web server to provide an access point for players and to handle bot uploads (this gets rid of the network share).

The requirements are very basic: initially I envisage serving a single page with an edit box and a "Go" button (= upload to server, compile & publish into game); I expect no more than 20 concurrent users with not more than one bot upload across all users every 5 or 10 seconds; I need to hold minimal state for each users (just a name) and I need to return compiler error messages to the user. Note that game screen updates would NOT be displayed in the browser but on a projector attached to the server machine. And primarily to allow for the simplest possible setup (double click on the game server .jar) I think it would be nice to run the web server in a background thread within the existing game server.

What is the most appropriate way to do this? Should I use some existing framework, like Play or Lift? Is there existing code for doing something very similar to this? Is it even reasonable to plan to run a web server in a background thread like this? Any advice is appreciated.

回答1:

One of the most used small, embeddable web servers / servlet containers in the Java world is Jetty. Since Scala can easily use Java libraries, it should be easy to use this from Scala.

This page shows some simple examples (in Java) on how to start it as an embedded HTTP server.



回答2:

Embedded web servers is exactly what Unfiltered was made for. The basic philosophy for Unfiltered is that the web server is just a library you call from your code, instead of your code being something the web framework calls.



回答3:

Embedding Jetty is fairly easy, being one of the primary goals for the Jetty project. If you needs are simple, this is the quickest route. I suspect you will quickly need a more robust solution (models, routing, templates, etc) so using a framework like Lift or Play Framework would be a better idea.



回答4:

Here are a couple of different examples of embedding Java containers and Scala frameworks:

  • Netty + Finagle
  • Jetty + Lift

While both of these talk about running the application on Heroku, you can just run them as Scala applications standalone.



回答5:

val webServer = new Thread("Web Server") {
  def response(text: String, code: String = "200 OK") =
    """HTTP/1.0 """ + code + """
  Content-Type: text/html
  Content-Length: """ + text.length + """

  """ + text

  override def run {
    for(port <- env.webPort) {
      val ss = new ServerSocket(port)
      while (true) try {
        val s = ss.accept
        try { s.getOutputStream.write(response(someStuff.toString).getBytes)
        } finally { s.close }
      } catch { case ie: InterruptedException => return }
    }
  }
}

See also scala kittens



回答6:

As you want to provide a framework, I think that the best solution is to use an existing framework, that way you won't have to bother with re-inventing stuff.

From my personal experience, which is really subjective, I would suggest you to use Lift as I know that it is very powerful for the support of sessions, global snippets and other stuff. You can try to extend the classical chat app that is used as an example of how lift works, testing wether it is useful for your use or not shouldn't be long.