An intentionally slow Scala 3 HTTP server

For a variety of reasons I recently wrote an “intentionally slow” HTTP socket server using Scala 3. Though I also wanted to test some things with Scala 3, the main reason for writing it is so I can test some client-side code, and make sure I handle server-side timeouts correctly.

The server-side code

The important part of the Scala 3 server-side code looks like this:

@main def SlowSocketServer =
    val serverResponseDelayTimeMs = 1_000
    val serverPort = 5150

    val server = ServerSocket(serverPort)
    while true do
        // “Listens for a connection to be made to this socket and accepts it”
        val socket = server.accept()

        // simulate a slow server response
        Thread.sleep(serverResponseDelayTimeMs)

        val in = BufferedReader(InputStreamReader(socket.getInputStream))
        val out = PrintWriter(socket.getOutputStream)

        // this works, but i don’t know if it 100% meets the standard.
        // might need a `\r` at the end of every line.
        out.print(httpResponse(serverResponseDelayTimeMs))
        out.flush()

        // read the input from the client.
        // LazyList used to be known as Stream. can also use Iterator.
        val s = LazyList.continually(in.readLine())
            .takeWhile(_.length != 0)
            .mkString("\n")

        out.close
        in.close
        socket.close
end SlowSocketServer

Test clients

I’ve tested this server-side code with a few different HTTP clients. Here are two examples of how to test it with curl commands:

$ curl http://localhost:5150
Have a nice day!

$ curl --head http://localhost:5150
HTTP/1.1 200 OK
Date: Fri Dec 04 10:38:05 MST 2020
Server: SlowServer
Content-Type: text/plain
Delay-Time: 1000 ms
Connection: Closed

Project source code

If you’re interested, you can find the complete project source code here:

Scala 3 scalac options

You’ll see that in that project I’m also experimenting with scalac options, so I set the scalacOptions field in my build.sbt file as shown here:

name := "ScalaSlowSocketServer"
version := "0.1"
scalaVersion := "3.0.0-M2"
useScala3doc := true

fork in run := true

scalacOptions ++= Seq(
    "-deprecation",
    "-explain",
    "-explain-types",
    "-new-syntax",
    "-unchecked",
    "-Xfatal-warnings",
    "-Xmigration"
)

As a final note, the fork part is necessary because I have been running the code from inside the sbt shell, and with this setting I can type Ctrl-C. That stops my server, but doesn’t kill the sbt session.

Summary

In summary, if you ever need an intentionally-slow HTTP server, I hope this example is helpful.