SIMPLY SCALA SERVER

This project provides a fast & ultra-lightweight http server (with simpleframework)
with an API dedicated to define server’s routes (request-response), start & stop server.

This works in a Java 6+ environment

The actual project release version is 0.5

Be careful ! Between 0.2 & 0.3 version :

  • signature of ServerResponse was change(ServerResponse => StaticServerResponse & DynamicServerResponse). It is not retro-compatible !
  • you can’t use String to type your content-type response but fr.simply.util.ContentType builder or some fr.simply.util._ objects

Be careful ! Between 0.3 & 0.4 version :

  • 0.4 version works under scala 2.10.x & don’t support 2.9.x version anymore

This project is under test. See test code coverage report here

Roadmap

  • custom server’s default response OK
  • GET request with params OK
  • use * pattern for path route param OK
  • check if chosen port was not already used OK
  • POST request OK
  • cross compilation OK
  • push on maven central repository OK
  • Dynamic ServerResponse OK
  • build in scala 2.10 OK
  • Stub Server Fixture Trait OK
  • PUT request OK
  • HEAD request OK
  • DELETE request OK
  • OTPIONS, PATCH request OK
  • set response headers OK
  • Java API TODO
  • extends simplyscala-server TODO

Installation

Git repo

simplyscala-server is a SBT project.
It use 0.12 sbt version.

Maven dependency


    <dependency>
        <groupId>com.github.simplyscala</groupId>
        <artifactId>simplyscala-server_2.10</artifactId>
        <version>0.5</version>
    </dependency>

SBT dependency


    libraryDependencies += "com.github.simplyscala" %% "simplyscala-server" % "0.5"
Only the following Scala versions 2.10.x are currently supported.

Play! specific dependency management

In your play! project Build file :


    object ApplicationBuild extends Build {

        val appDependencies = Seq (
            "com.github.simplyscala" %% "simplyscala-server" % "0.5"
        )
    }

Simple JAR file

0.5 jar version

Try SNAPSHOT version

You could be tempted to try SNAPSHOT version to test project’s next features.

with Maven


<project ...>

   <repositories>
      <repository>
         <id>maven snapshot</id>
         <url>https://oss.sonatype.org/content/repositories/snapshots</url>
      </repository>
   </repositories>

   ...

   <dependency>
      <groupId>com.github.simplyscala</groupId>
      <artifactId>simplyscala-server_2.10</artifactId>
      <version>0.6-SNAPSHOT</version>
    </dependency>

with SBT


   resolvers += "Sonatype OSS Snapshots" at "https://oss.sonatype.org/content/repositories/snapshots"

   libraryDependencies += "com.github.simplyscala" %% "simplyscala-server" % "0.6-SNAPSHOT"

Usage

In order to use SimplyScala server API, import as follows:

import fr.simply._

Basic Usage


    val server = new StubServer(8080).start
    server.stop

By default, with no routes defined, SimplyScala server returns a 404 text/plain response with “error” in body

Server’s custom default response

You can define your own server’s default response like this :

val server = new StubServer(8080).defaultResponse(ContentType("text/plain"), "value return in body", 400).start

Build GET request routes with param


    val route = GET (
        path = "/test",
        params = Map("param1" -> "toto"),
        response = StaticServerResponse(ContentType("text/plain"), "yo", 200)
    )

    val server = new StubServer(8080, route).start

when you request http://localhost:8080/test?param1=toto, the server returns with an http code 200 and a “text/plain”-typed body containing “yo”.

Build POST request route with param


    val route = POST (
        path = "/test",
        params = Map("param1" -> "toto"),
        response = StaticServerResponse(ContentType("text/plain"), "yo", 200)
    )

    val server = new StubServer(8080, route).start

Build request with dynamic server response

Since 0.3 version, you able to define some dynamic server response.
To do that, you must define function typed as Request => StaticServerResponse, which permit use some parameters of the
server request to build a response.


    import org.simpleframework.http.Request
    ...

    val dynamicResponse: Request => StaticServerResponse = {
        request =>
            println("I use dynamic code !!!")
            StaticServerResponse(Text_Plain, "OK dynamic", 200)
        }

    val route = GET (
        path = "/test",
        params = Map("param1" -> "toto"),
        response = DynamicServerResponse(dynamicResponse)
    )

    val server = new StubServer(8080, route).start

What to do when the configured port is already used ?

Before creating the server instance, SimplyScala checks if the port you defined is not already in use.
If it is the case, SimplyScala will try the next value (+1) port to start the server.
You can retrieve the effective port like this:


    val server = new StubServer(8080).start
    server.portInUse    // perhaps 8081

ContentType util

with fr.simply.util._ import you can use some utilities to declare server’s content type


    val route = GET (
        path = "/test",
        params = Map("param1" -> "toto"),
        response = StaticServerResponse(Text_Plain, "yo", 200)
    )

    val server = new StubServer(8080, route).start

if we don’t have the needed content type util you can use ContentType("your content type")

Uses in test context

Simple usage in test context

simplyscala-server is particularly useful in unit test context.
You can use it like that with ScalaTest :


    class StubServerTest extends FunSuite {

        test("a test which needed simplyscala-server") {
            val route = GET (
                path = "/test",
                params = Map("param" -> "toto"),
                response = StaticServerResponse(Text_Plain, "yo", 200)
            )

            val server = new StubServer(8080, route).start

            someHttpRequest("http://localhost:%s/test?param=toto".format(server.portInUse))
        }
    }

You you do not have to stop the server thanks to when a define port is already used, simplyscala-server start server with next port and return reference to it via portInUse method.

using fixture to manipulate immutable server reference (in 0.4 version)

If you want to stop the server & stay immutable, you can use StubServerFixtureTrait like that



import org.scalatest.FunSuite
import fr.simply.{StaticServerResponse, GET}
import fr.simply.util.Text_Plain
import fr.simply.fixture.StubServerFixture

    class StubServerFixtureTest extends FunSuite with StubServerFixture {

        test("test stub server fixture") {
            val route = GET (
                path = "/test",
                params = Map("param1" -> "toto"),
                response = StaticServerResponse(Text_Plain, "yo", 200)
            )

            withStubServerFixture(8080, route) { server =>
                // you can continue your test with server reference
                // in this fixture your server stub is started
                // at the en d of this fixture your server is stopped
            }
        }
    }

ScalaTestFixture

adding values in server response’s header (in 0.5 version)

You might need manage server response header, for example in the case of HEAD response.



import org.scalatest.FunSuite
import fr.simply.{StaticServerResponse, HEAD}
import fr.simply.util.Text_Plain
import fr.simply.fixture.StubServerFixture

    class StubServerFixtureTest extends FunSuite with StubServerFixture {

        test("test stub server fixture") {
            val route = HEAD (
                path = "/test",
                response = StaticServerResponse(Text_Plain, "", 200, Map("headerName" -> "value"))
            )

            withStubServerFixture(8080, route) { server =>
                // the server will have key-value pair "headerName" -> "value" in header response
            }
        }
    }

footpage

This file is written with .textile extension

Maven Repository Usage Guide
Sonatype project JIRA Page