Check Socko out on GitHub


Socko User Guide - Serving Dynamic HTTP Content


Parsing Data  

Parsing Query Strings  

You can access query string parameters using HttpRequestEvent.

// For mypath?a=1&b=2
  val qsMap = event.endPoint.queryStringMap
  assert (qsMap("a") == "1")

See the query string and post data example for more details.

Parsing Post Form Data  

If you do not have to support file uploads and your post form data content type is application/x-www-form-urlencoded data, you can access the form data using HttpRequestEvent.

// For firstName=jim&lastName=low
  val formDataMap = event.request.content.toFormDataMap
  assert (formDataMap("firstName") == "jim")

See the query string and post data example for more details.

Parsing File Uploads  

If you intend to support file uploads, you need to use Netty’s HttpPostRequestDecoder.

The following example extracts the description field as well as a file that was posted.

  // The following form has a file upload input named "fileUpload" and a description
  // field named "fileDescription".
  // ------WebKitFormBoundaryThBHDfQBdTlMy3sK
  // Content-Disposition: form-data; name="fileUpload"; filename="myfile.txt"
  // Content-Type: text/plain
  // file contents
  // ------WebKitFormBoundaryThBHDfQBdTlMy3sK
  // Content-Disposition: form-data; name="fileDescription"
  // this is my file upload
  // ------WebKitFormBoundaryThBHDfQBdTlMy3sK--

  val decoder = new HttpPostRequestDecoder(HttpDataFactory.value, event.nettyHttpRequest)
  val descriptionField = decoder.getBodyHttpData("fileDescription").asInstanceOf[Attribute]
  val fileField = decoder.getBodyHttpData("fileUpload").asInstanceOf[FileUpload]
  val destFile = new File(msg.saveDir, fileField.getFilename)

See the file upload example for more details.

RESTful Web Services  

Socko’s RestHandler class provides a quick way to expose your Akka actors as REST end points. You will be able to invoke your Akka actors using Javascript in a web browser app and from other HTTP clients.

It also natively supports Swagger. With Swagger, you will be able to provide your users with your API documentation straight from your code.

The current limitations of Socko’s RestHandler are: - Only JSON is supported. XML is not supported. - Only HTTP is supported. Web Socket is not supported. - This module relies on Scala reflection. Reflection is tagged as experimental in Scala 2.10. There is also an issue with thread safety. For unit tests to work, you have to execute them serially (in sbt set parallelExecution in Test := false). Also, instancing RestRegistry in Step #5 must be performed in a single thead.

To use the RestHandler class, follow the 5 steps below. The example code can be found in the Pet Shop example REST app.

Step 1. Installation  

In order to use the Socko RESTful Web Service framework, you need to add an extra dependency.

Add the following to your build.sbt. Replace X.Y.Z with the version number.

libraryDependencies += "org.mashupbots.socko" %% "socko-rest" % "X.Y.Z"

Step 2. Implement your Data Model  

Define your model as case classes.

case class Tag(id: Long, name: String)
  case class Category(id: Long, name: String)
  case class Pet(id: Long, category: Category, name: String, photoUrls: List[String], tags: List[Tag], status: String)

You can specify additional information to describe the properties in your data model using RestModelMetaData. For example, to add more information about a Pet, create a companion Pet object that extends RestModelMetaData. Then, provide additional meta data using RestPropertyMetaData.

object Pet extends RestModelMetaData {
    val modelProperties = Seq(
      RestPropertyMetaData("name", "Name of the pet"),
      RestPropertyMetaData("status", "pet status in the store", Some(AllowableValuesList(List("available", "pending", "sold")))))

Step 3. Implement your Business Logic Actors  

Socko RestHandler uses a Request/Response model.

Incoming request data is deserialized into RestRequest. Similarly, an outgoing RestResponse is serialized into response data.

The following is an example implementation of a REST operation that returns a Pet given the pet’s id as input.

case class GetPetRequest(context: RestRequestContext, petId: Long) extends RestRequest
  case class GetPetResponse(context: RestResponseContext, pet: Option[Pet]) extends RestResponse

  class PetProcessor() extends Actor with {
    def receive = {
      case req: GetPetRequest =>
        val pet = PetData.getPetById(req.petId)
        val response = if (pet != null) {
          GetPetResponse(req.context.responseContext, Some(pet))
        } else {
          GetPetResponse(req.context.responseContext(404), None)
        sender ! response

Your request and response must extend from RestRequest and RestResponse respectively as illustrated in GetPetRequest and GetPetResponse. Your request and resposne must declare context as the first parameter. Subsequement parameters can contain primitives and your data model classes.

Step 4. Register your REST Operation  

In order to notify RestHandler to the existance of your actor, you need to regsiter it.

Registering involves creating a Scala object that extends RestRegistration.

At minimum, you must provide the method, path, bindings for your request parameters and the actor that you wish to use to process incoming requests.

object GetPetRegistration extends RestRegistration {
    val method = Method.GET
    val path = "/pet/{petId}"
    val requestParams = Seq(PathParam("petId", "ID of pet that needs to be fetched"))
    def processorActor(actorSystem: ActorSystem, request: RestRequest): ActorRef = actorSystem.actorOf(Props[PetProcessor])

You can also specify additional information to describe your REST operation.

object GetPetRegistration extends RestRegistration {
    val method = Method.GET
    val path = "/pet/{petId}"
    val requestParams = Seq(PathParam("petId", "ID of pet that needs to be fetched"))
    def processorActor(actorSystem: ActorSystem, request: RestRequest): ActorRef = actorSystem.actorOf(Props[PetProcessor])
    override val name = "getPetById"
    override val description = "Find pet by ID"
    override val notes = "Returns a pet based on ID"
    override val errors = Seq(Error(400, "Invalid ID supplied"), Error(404, "Pet not found"))

A key part of registration is defining how you return your actor using processorActor(). In the Pet Shop example REST app, we have provided 3 example scenarios:

Step 5. Using the REST Handler  

In order to use RestHandler, you must first instance RestRegistry. The registry will search the code base for your RestRegistrations.

Using an Akka router, you can then instance RestHandler with the RestRegistry.

Finally, add the RestHandler to your route and start Socko web server.

The following example illustrates:

  // STEP #1 - Define Actors and Start Akka
  val actorConfig = """
	akka {
	  event-handlers = ["akka.event.slf4j.Slf4jEventHandler"]
	  actor {
	    deployment {
	      /rest-router {
	        router = round-robin
	        nr-of-instances = 5

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

  val restRegistry = RestRegistry("",
    RestConfig("1.0", "http://localhost:8888/api", reportRuntimeException = ReportRuntimeException.All))

  val restRouter = actorSystem.actorOf(Props(new RestHandler(restRegistry)).withRouter(FromConfig()), "rest-router")

  // STEP #2 - Define Routes
  val routes = Routes({
    case HttpRequest(request) => request match {
      case PathSegments("swagger-ui" :: relativePath) => {
        // Serve the static swagger-ui content from resources
        staticContentHandlerRouter ! new StaticResourceRequest(request, relativePath.mkString("swaggerui/", "/", ""))
      case PathSegments("api" :: relativePath) => {
        // REST API - just pass the request to the handler for processing
        restRouter ! request
      case GET(Path("/favicon.ico")) => {

  // STEP #3 - Start and Stop Socko Web Server
  def main(args: Array[String]) {
    // Start web server
    val config = WebServerConfig(webLog = Some(WebLogConfig()))
    val webServer = new WebServer(config, routes, actorSystem)
    Runtime.getRuntime.addShutdownHook(new Thread {
      override def run {

    System.out.println("Open your browser and navigate to http://localhost:8888/swagger-ui/index.html")


The RestConfig class is used to configure the REST handler. It is specified when instancing RestRegistry.

Required settings are:

Like other settings, you can set the values programmatically or via an external Akka configuration file. See RestConfig for more details.

Supported Data Types  

The supported data types aligns with swagger.

Option, Seq or Array of the above are also supported.

Web Sockets  

For a detailed discussion on how web sockets work, refer to RFC 6455.

Prior to a web socket connection being established, a web socket handshake must take place. In Socko, a WebSocketHandshakeEvent is fired when a handshake is required.

After a successful handshake, WebSocketFrameEvent is fired when a web socket text or binary frame is received.

The following route from our web socket example app illustrates:

val routes = Routes({
      case HttpRequest(httpRequest) => httpRequest match {
        case GET(Path("/html")) => {
          // Return HTML page to establish web socket
          actorSystem.actorOf(Props[WebSocketHandler]) ! httpRequest
        case Path("/favicon.ico") => {
          // If favicon.ico, just return a 404 because we don't have that file
      case WebSocketHandshake(wsHandshake) => wsHandshake match {
        case Path("/websocket/") => {
          // To start Web Socket processing, we first have to authorize the handshake.
          // This is a security measure to make sure that web sockets can only be established at your specified end points.
      case WebSocketFrame(wsFrame) => {
        // Once handshaking has taken place, we can now process frames sent from the client
        actorSystem.actorOf(Props[WebSocketHandler]) ! wsFrame

Note that for a web socket handshake, you only need to call wsHandshake.authorize() in order to approve the connection. This is a security measure to make sure that web sockets can only be established at your specified end points. Dispatching to an actor is not required and not recommended.

You can also specify subprotocols and maximum frame size with authorization. If not specified, the default is no subprotocol support and a maximum frame size of 100K.

// Only support chat and superchat subprotocols and max frame size of 1000 bytes
wsHandshake.authorize("chat, superchat", 1000)

If you wish to push or broadcast messages to a group of web socket connections, use WebSocketBroadcaster. See the example web socket ChatApp for usage.