spray client

Johannes Rudolph edited this page Aug 14, 2013 · 10 revisions

. . . Deprecation Note

This documentation is for release 0.9.0 (from 03/2012), which is built against Scala 2.9.1 and Akka 1.3.1 (see Requirements for more information). Most likely, this is not the place you want to look for information. Please turn to the main spray site at http://spray.io for more information about other available versions.

. . .

spray-client provides a logic layer on top of the rather low-level spray-can HttpClient offering the following features:

  • Reliable, fast and completely asynchronous HTTP client built on Akka Futures
  • Connection pooling
  • Rich, immutable HTTP model
  • Compression / Decompression
  • Marshalling / Unmarshalling from and to your custom types
  • HTTP Basic Auth
  • Full support for HTTP pipelining

Currently, HTTP streaming (i.e. chunked transfer encoding) is not yet fully supported on the spray-client level (even though the underlying spray-can HttpClient does support it), i.e. you cannot send chunked requests and chunked responses will always be fully buffered before being dispatched to your application).

Also, spray-client currently does not support SSL/TLS. We realize that this is a show-stopper for many applications, we are working hard on bringing you HTTP support with the next release.

Basic Usage

The central element in spray-client is the HttpConduit, which is an abstraction over a number of HTTP connections to a specific HTTP server (the underlying spray-can HttpClient works on the level of one single HTTP connection). You create an HttpConduit like this:

val conduit = new HttpConduit("github.com")

The constructor takes a hostname and optionally a port and and a ConduitConfig. The latter lets you specify the maximum number of connections the HttpConduit will open to the target host as well as a DispatchStrategy. A DispatchStrategy determines how outgoing requests are scheduled across the several connections the HttpConduit manages. Currently spray-client comes with two predefined strategies:

Once you've got a hold of an HttpConduit instance you can call conduit.sendReceive to send a request:

val responseFuture = conduit.sendReceive(HttpRequest(GET, uri = "/"))

You get back a Future[HttpResponse], which you can then work with as you would with any other Akka Future. You can reuse one HttpConduit for as many requests as you like (as long as all of them are for the same host). When your code has finished talking to the HTTP host you should call conduit.close() to close the connection(s) and free any respective resources. (Be careful not to call close before all response futures have been completed!)

The Message Pipeline

The conduits sendReceive member has type HttpRequest => Future[HttpResponse], which is nice but leaves the creation of requests and interpretation of responses completely to you. Many times you actually want to send and/or receive custom objects that need to be serialized to HTTP requests or deserialized from HTTP responses. spray-client supports this via the concept of a "MessagePipeline".

Check out this snippet:

val conduit = new HttpConduit("maps.googleapis.com") {
  val pipeline = (
    simpleRequest[Order]
    ~> encode(Gzip)
    ~> authenticate(BasicHttpCredentials("bob", "secret"))
    ~> sendReceive
    ~> decode(Deflate)
    ~> unmarshal[OrderConfirmation]
  )
}

Assuming you have defined the custom types Order and OrderConfirmation as well as a Marshaller for Order and an Unmarshaller for OrderConfirmation (see Marshalling and Unmarshalling) this snippet defines a "MessagePipeline" of type SimpleRequest[Order] => Future[OrderConfirmation], which you can use like this:

val orderConfFuture = conduit.pipeline(Post("/orders"))

The various pipeline elements that you can chain together with the ~> operator are defined in the MessagePipelining trait, which the HttpConduit mixes in.

Any errors that might occur during pipeline execution will cause the resulting future to be completed with a respective exception.

Example

The spray source code repository contains an example project for spray-client, called spray-client-example that you can run like this:

  1. Clone the spray source code repository
  2. cd into the base directory
  3. Run sbt "project spray-client-example" run

The example does two independent things:

  1. Fetch and display the response of "github.com" to a GET request to "/".
  2. Use the Google Maps API to fetch and display the elevation of Mt. Everest

This is it's main source file, which might serve as a starting point for you own spray-client endeavors.