Skip to content
This repository has been archived by the owner on Apr 24, 2024. It is now read-only.
Mathias edited this page Nov 17, 2011 · 44 revisions

spray

spray is a suite of lightweight Scala libraries for building and consuming RESTful web services on top of Akka. It sports the following main features:

  • Completely asynchronous, non-blocking, actor-based request and response processing for efficiently handling very high numbers of concurrent connections
  • Powerful, flexible and extensible internal Scala DSL for declaratively defining your web service behavior
  • Immutable model of the HTTP protocol, decoupled from the underlying web server / servlet container
  • Full testability of your REST services, without the need to fire up containers or actors

Currently spray consists of the following components:

  • spray-can, a low-level, low-overhead, high-performance, fully asynchronous HTTP/1.1 server and client
  • , a high-level framework for elegantly defining RESTful web services
  • spray-client, a layer on top of the low-level spray-can HttpClient offering higher-level client functionality
  • spray-json, a lightweight, clean and simple JSON implementation in Scala

spray-server and spray-client share one github repository (this one), whereas spray-can and spray-json live in their own.

The latest stable release is 0.8.0, which is built against Scala 2.9.1 and Akka 1.2 (see Requirements for more information).

Very Basic spray-server Example

import cc.spray._

trait HelloService extends Directives {
  val helloService = {
    path("hello") {
      get { _.complete(<h1>Say hello to Spray</h1>) }
    }
  }
}

Latest Blog Posts

Support, Feedback, General Discussion

Please use the http://groups.google.com/group/spray-user/ mailing list!
You should also follow us on twitter: @spraycc

Longer Sample Code

The following is a spray-server web service definition that tries to show off as many features as possible. The resulting service does not really do anything useful but its definition should give you a pretty good idea of what is possible with spray:

val service = {
  path("orders") {
    authenticate(httpBasic(realm = "admin area")) { user =>
      get {
        cacheResults(LruCache(maxEntries = 1000, ttl = 30.minutes)) {
          encodeResponse(Deflate) {
            // marshal custom object with in-scope marshaller
            _.complete(getOrdersFromDB())
          }
        }
      } ~
      post {
        (decodeRequest(Gzip) | decodeRequest(NoEncoding)) {
          // unmarshal with in-scope unmarshaller
          content(as[Order]) { order =>
            // transfer to newly spawned actor
            detach { ctx =>
              // ... write order to DB
              ctx.complete("Order received")
            }
          }
        }
      }
    }
  } ~
  // extract URI path element as Int
  pathPrefix("order" / IntNumber) { orderId =>
    path("") {
      // method tunneling via query param
      (put | parameter('method ! "put")) {
        // form extraction from multipart or www-url-encoded forms
        formFields('email, 'total as[Money]).as(Order) { order => ctx =>
          // transfer request handling to custom actor
          myDbActor ! Update(order, ctx)
        }
      } ~
      get {
        // JSONP support
        jsonpWithParameter("callback") {
          // use in-scope marshaller to create completer function
          produce(instanceOf(Order)) { complete =>
            _ => complete(getOrderFromDB(orderId))
          }
        }
      }                
    } ~
    path("items") {
      get {
        // parameters to case class extraction
        parameters('size as[Int], 'color ?, 'dangerous ? "no")
                .as(OrderItem) { orderItem =>
          // ... route using case class instance created from
          // required and optional query parameters
        }
      }
    }
  } ~
  path("documentation") {
    // cache responses to GET requests
    cache {
      // serve up static content from a JAR resource
      getFromResourceDirectory("docs")
    }
  }
}

License

spray is released under the Apache License 2.0.

Portions of the immutable HTTP model are
copyright (C) 2010-2011 by the BlueEyes Web Framework Team