Timeout Handling

spray-routing itself does not perform any timeout checking, it relies on the underlying spray-can or spray-servlet module to watch for request timeouts. Both, the spray-can HTTP Server and spray-servlet, define a timeout-handler config setting, which allows you to specify the path of the actor to send spray.http.Timedout messages to whenever a request timeout occurs. By default all Timedout messages go to same actor that also handles “regular” request, i.e. your service actor.

Timedout is a simple wrapper around HttpRequest or ChunkedRequestStart instances:

case class Timedout(request: HttpRequestPart with HttpMessageStart)

If a Timedout messages hits your service actor runRoute unpacks it and feeds the wrapped request, i.e. the one that timed out, to the timeoutRoute defined by the the HttpService. The default implementation looks like this:

def timeoutRoute: Route = complete(
  InternalServerError,
  "The server was not able to produce a timely response to your request.")

If you’d like to customize how your service reacts to request timeouts simply override the timeoutRoute method.

Alternatively you can also “catch” Timedout message before they are handled by runRoute and handle them in any way you want. Here is an example of what this might look like:

import spray.http._
import spray.routing._

class MyService extends HttpServiceActor {
  def receive = handleTimeouts orElse runRoute(myRoute)

  def myRoute: Route = `<my-route-definition>`

  def handleTimeouts: Receive = {
    case Timedout(x: HttpRequest) =>
      sender ! HttpResponse(StatusCodes.InternalServerError, "Too late")
  }
}