Skip to content
jenshaase edited this page Feb 24, 2012 · 5 revisions

Normally all your routing logic runs within the context of its HttpService actor, which is fine, as long as your code does not contain blocking calls (e.g. to I/O) or really expensive operations. For all other cases there are two ways of moving request handling off the HttpService actor to another actor: explicitly or via the detach directive.

Explicitly moving Request Handling to a custom Actor

You can ship off request handling to another actor at any time like this:

get { myActor ! _ }

Your actor should be prepared to receive a RequestContext object, which it can handle in any way it wants, e.g. with the help another, "personal" route.

The detach Directive

The detach directive simplifies the common case of transferring the handling of the current request to another, newly spawned actor. For example in the following scenario:

path("some" / "resource") {
  get {
    detach {
      ... // expensive logic for retrieving the resource representation
    }
  } ~
  put {
    ...          
  }
}

the "expensive logic" will not run within the context of the main routes HttpService actor but its own private actor.

Note that sprays "continuation-style" route combinators have an important side effect, that might not be obvious on first sight. Consider this slightly changed example:

path("some" / "resource") {
  detach {
    get {
      ... // expensive logic for retrieving the resource representation
    }
  } ~
  put {
    ... // PUT logic          
  }
}

At first sight this seems identical to the example above, however, there is one important difference. This time, during route processing, the detach directive is encountered first, before the get filter is run. Therefore the request handling is split off to a fresh actor for all requests to the "some/resource" path, even non-GET requests. Even though the route description doesn't make it obvious also the PUT logic is run in the newly spawned actor. This example is equivalent to the following, more readable one (which should therefore be preferred, if intended):

path("some" / "resource") {
  detach {
    get {
      ... // expensive logic for retrieving the resource representation
    } ~
    put {
      ... // PUT logic          
    }
  } 
}

Clone this wiki locally