withRequestTimeoutResponse

Signature

def withRequestTimeoutResponse(handler: HttpRequest 

Description

Allows customising the HttpResponseHttpResponse that will be sent to clients in case of a Request timeout.

See also withRequestTimeout or withoutRequestTimeout if interested in dynamically changing the timeout for a given route instead.

Warning

Please note that setting handler is inherently racy as the timeout is measured from starting to handle the request to its deadline, thus if the timeout triggers before the withRequestTimeoutResponse executed it would have emitted the default timeout HttpResponse.

In practice this can only be a problem with very tight timeouts, so with default settings of request timeouts being measured in seconds it shouldn’t be a problem in reality (though certainly a possibility still).

To learn more about various timeouts in Apache Pekko HTTP and how to configure them see Pekko HTTP Timeouts.

Example

Scala
sourceval timeoutResponse = HttpResponse(
  StatusCodes.EnhanceYourCalm,
  entity = "Unable to serve response within time limit, please enhance your calm.")

val route =
  path("timeout") {
    withRequestTimeout(100.milli) { // racy! for a very short timeout like 1.milli you can still get 503
      withRequestTimeoutResponse(request => timeoutResponse) {
        val response: Future[String] = slowFuture() // very slow
        complete(response)
      }
    }
  }

// check
Get("/timeout") ~!> route ~> check {
  status should ===(StatusCodes.EnhanceYourCalm) // the timeout response
}
Java
sourcefinal Duration timeout = Duration.create(100, TimeUnit.MILLISECONDS);
CompletionStage<String> slowFuture = new CompletableFuture<>();

HttpResponse enhanceYourCalmResponse =
    HttpResponse.create()
        .withStatus(StatusCodes.ENHANCE_YOUR_CALM)
        .withEntity("Unable to serve response within time limit, please enhance your calm.");

final Route route =
    path(
        "timeout",
        () ->
            withRequestTimeout(
                timeout,
                () ->
                    // racy! for a very short timeout like 1.milli you can still get 503
                    withRequestTimeoutResponse(
                        (request) -> enhanceYourCalmResponse,
                        () -> {
                          return completeOKWithFutureString(slowFuture); // very slow
                        })));

// test:
StatusCode statusCode = runRoute(route, "timeout").get().status();
assert (StatusCodes.ENHANCE_YOUR_CALM.equals(statusCode));