recoverRejections

Signature

def recoverRejections(f: immutable.Seq[Rejection] 

Description

Low level directive – unless you’re sure you need to be working on this low-level you might instead want to try the handleRejections directive which provides a nicer DSL for building rejection handlers.

Transforms rejections from the inner route with an immutable.Seq[Rejection] => RouteResult function. a Function<Iterable<Rejection>, RouteResult>. A RouteResultRouteResult is either a Complete(HttpResponse(...)) Complete containing the HttpResponseHttpResponse or a Rejected(rejections). Rejected containing the rejections.

Note

To learn more about how and why rejections work read the Rejections section of the documentation.

Example

Scala
sourceval authRejectionsToNothingToSeeHere = recoverRejections { rejections =>
  if (rejections.exists(_.isInstanceOf[AuthenticationFailedRejection]))
    Complete(HttpResponse(entity = "Nothing to see here, move along."))
  else if (rejections == Nil) // see "Empty Rejections" for more details
    Complete(HttpResponse(StatusCodes.NotFound, entity = "Literally nothing to see here."))
  else
    Rejected(rejections)
}
val neverAuth: Authenticator[String] = creds => None
val alwaysAuth: Authenticator[String] = creds => Some("id")

val route =
  authRejectionsToNothingToSeeHere {
    pathPrefix("auth") {
      concat(
        path("never") {
          authenticateBasic("my-realm", neverAuth) { user =>
            complete("Welcome to the bat-cave!")
          }
        },
        path("always") {
          authenticateBasic("my-realm", alwaysAuth) { user =>
            complete("Welcome to the secret place!")
          }
        })
    }
  }

// tests:
Get("/auth/never") ~> route ~> check {
  status shouldEqual StatusCodes.OK
  responseAs[String] shouldEqual "Nothing to see here, move along."
}
Get("/auth/always") ~> route ~> check {
  status shouldEqual StatusCodes.OK
  responseAs[String] shouldEqual "Welcome to the secret place!"
}
Get("/auth/does_not_exist") ~> route ~> check {
  status shouldEqual StatusCodes.NotFound
  responseAs[String] shouldEqual "Literally nothing to see here."
}
Java
sourceimport org.apache.pekko.http.javadsl.server.directives.SecurityDirectives.ProvidedCredentials;

import static org.apache.pekko.http.javadsl.server.Directives.authenticateBasic;
import static org.apache.pekko.http.javadsl.server.Directives.recoverRejections;

final Function<Optional<ProvidedCredentials>, Optional<Object>> neverAuth =
    creds -> Optional.empty();
final Function<Optional<ProvidedCredentials>, Optional<Object>> alwaysAuth =
    creds -> Optional.of("id");

final Route originalRoute =
    pathPrefix(
        "auth",
        () ->
            Directives.concat(
                path(
                    "never",
                    () ->
                        authenticateBasic(
                            "my-realm",
                            neverAuth,
                            obj -> complete("Welcome to the bat-cave!"))),
                path(
                    "always",
                    () ->
                        authenticateBasic(
                            "my-realm",
                            alwaysAuth,
                            obj -> complete("Welcome to the secret place!")))));

final Function<Iterable<Rejection>, Boolean> existsAuthenticationFailedRejection =
    rejections ->
        StreamSupport.stream(rejections.spliterator(), false)
            .anyMatch(r -> r instanceof AuthenticationFailedRejection);

final Route route =
    recoverRejections(
        rejections -> {
          if (existsAuthenticationFailedRejection.apply(rejections)) {
            return RouteResults.complete(
                HttpResponse.create().withEntity("Nothing to see here, move along."));
          } else if (!rejections
              .iterator()
              .hasNext()) { // see "Empty Rejections" for more details
            return RouteResults.complete(
                HttpResponse.create()
                    .withStatus(StatusCodes.NOT_FOUND)
                    .withEntity("Literally nothing to see here."));
          } else {
            return RouteResults.rejected(rejections);
          }
        },
        () -> originalRoute);

// tests:
testRoute(route)
    .run(HttpRequest.GET("/auth/never"))
    .assertStatusCode(StatusCodes.OK)
    .assertEntity("Nothing to see here, move along.");
testRoute(route)
    .run(HttpRequest.GET("/auth/always"))
    .assertStatusCode(StatusCodes.OK)
    .assertEntity("Welcome to the secret place!");
testRoute(route)
    .run(HttpRequest.GET("/auth/does_not_exist"))
    .assertStatusCode(StatusCodes.NOT_FOUND)
    .assertEntity("Literally nothing to see here.");