Check Socko out on GitHub

SOCKO WEB SERVER

Socko User Guide - Serving Static HTTP Content

Table of Contents

Socko’s StaticContentHandler is used for serving static files and resources.

It supports HTTP compression, browser cache control and content caching.

Actor Setup

We recommend that you run StaticContentHandler with a router and with its own dispatcher. This is because StaticContentHandler contains blocking IO that must be isolated from other non-blocking actors.

For example, you can use the Pinned Dispatcher that dedicates a unique thread for each actor passed in as reference:

val actorConfig = """
      my-pinned-dispatcher {
        type=PinnedDispatcher
        executor=thread-pool-executor
      }
      akka {
        event-handlers = ["akka.event.slf4j.Slf4jEventHandler"]
        loglevel=DEBUG
        actor {
          deployment {
            /static-file-router {
              router = round-robin
              nr-of-instances = 5
            }
          }
        }
      }"""

    val actorSystem = ActorSystem("FileUploadExampleActorSystem", ConfigFactory.parseString(actorConfig))

    val handlerConfig = StaticContentHandlerConfig(
      rootFilePaths = Seq(contentDir.getAbsolutePath),
      tempDir = tempDir)

    val staticContentHandlerRouter = actorSystem.actorOf(Props(new StaticContentHandler(handlerConfig))
      .withRouter(FromConfig()).withDispatcher("my-pinned-dispatcher"), "static-file-router")

Configuration

The StaticContentHandlerConfig class is used to configure the serving of your static content.

Common settings are:

Like other Socko configurations, you can optionally load these settings from your Akka configuration file.

For example:

val actorConfig = """
      my-pinned-dispatcher {
        type=PinnedDispatcher
        executor=thread-pool-executor
      }
      my-static-content-handler {
		    root-file-paths="/tmp/x1, /tmp/x2"
		  }
      akka {
        event-handlers = ["akka.event.slf4j.Slf4jEventHandler"]
        loglevel=DEBUG
        actor {
          deployment {
            /static-file-router {
              router = round-robin
              nr-of-instances = 5
            }
          }
        }
      }"""

    val actorSystem = ActorSystem("FileUploadExampleActorSystem", ConfigFactory.parseString(actorConfig))

    val handlerConfig = MyStaticHandlerConfig(actorSystem)

    val staticContentHandlerRouter = actorSystem.actorOf(Props(new StaticContentHandler(handlerConfig))
      .withRouter(FromConfig()).withDispatcher("my-pinned-dispatcher"), "static-file-router")

    ...

    object MyStaticHandlerConfig extends ExtensionId[StaticContentHandlerConfig] with ExtensionIdProvider {
      override def lookup = MyStaticHandlerConfig
      override def createExtension(system: ExtendedActorSystem) =
        new StaticContentHandlerConfig(system.settings.config, "my-static-content-handler")
    }

Refer to the scala doc for more information.

Handling Requests

To serve a file or resource, send StaticFileRequest or StaticResourceRequest to the router.

val routes = Routes({
      case HttpRequest(request) => request match {
        case GET(Path("/foo.html")) => {
          staticContentHandlerRouter ! new StaticFileRequest(request, new File("/my/path/", "foo.html"))
        }
        case GET(Path("/foo.txt")) => {
          staticContentHandlerRouter ! new StaticResourceRequest(request, "META-INF/foo.txt")
        }
      }
    })

Note that for StaticResourceRequest, do not put the leading slash / in the path. (This is because behind the scenes we are using ClassLoader.getResourceAsStream())