On Github nexelem / preso-spray-intro
Tool for building REST/HTTP applications based on Scala and Akka
Fast and lightweight embedded HTTP server
DSL for constructing API
Marshalling system
Support for Servlet 3.0
Spray Http server is merged into Akka as Akka HTTP
Akka HTTP will be foundation for Play Framework
http://spray.io/blog/2013-05-24-benchmarking-spray/
http://blog.xebia.com/2013/08/02/on-the-mysteriously-fast-spray-can-web-server/
spray-can – low level, lightweight and fast HTTP server
spray-client – high lewel HTTP client
spray-caching – fast and lightweight in-memory caching
spray-routing – simple yet powerfull DSL for API constructing
spray-json – Marhalling data using JSON standard
spray-client: authorization, compression, marshalling
spray-servlet: building servlet webapps with spray-routing
Http Server binded to IO interface
Defined API
Actors for API calls processing
HTTP pipelining
HTTP persistent connections
SSL/TLS encryption
import spray.routing.SimpleRoutingApp object Main extends App with SimpleRoutingApp { implicit val system = ActorSystem("simle-example") startServer(interface = "localhost", port = 8080) { path("hello") { get { complete { <h1>Say hello to spray</h1> } } } } }
Based on `typesafe config` library
No initial configuration required
Automaticaly search `application.conf` file for configuration
Three types of timeout, `idle`, `request` and `timeout`
max-content-length - maximum content lenght (usefull when sending large files)
stats-support - support for statistics collection
Idle - after timeout idle connection is closed
Request - if request hasn't been responded sent Timedout message to timeout handler
Timeout - if request still hasn't been responded after Timedout message, server sent error response
Statistics - small overhead, switch off for production
type Route = RequestContext => Unit
Does not return results, all processing responses are returned to client by responder from RequestContext
May include simple path as well as path with variables (through PathMatcher system)
MAY BE BLOCKED
class UserApi(implicit val actorSystem: ActorSystem) ... { def userActor = actorSystem... val route = path("user") { post { handleWith { us: User => (userActor ? AddUser(us)).mapTo[User] } } ~ path("user" / Segment) { userLogin => delete { complete { "Kasowanie uzytkownika" } } }; }
Both may be used to handle requests/responses
`complete` may handle only marshalling while
handleWith = `unmarshall` + `complete`
Provides marshaller and umarshaller (by implicit mechanism)
New types can be easly added by creating custom formats that extends JsonFormat
trait CustomFormats { implicit object JsonDateFormat extends JsonFormat[DateTime] { def write(obj: DateTime) = { JsString(obj.toString()); } def read(json: JsValue): DateTime = json match { case JsString(date) => DateTime.parse(date) case _ => sys.error("Unable to parse date") } } }