recoverRejections
Signature
def recoverRejections(f: immutable.Seq[Rejection] ⇒ RouteResult): Directive0
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
-
val 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") {
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
-
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", () ->
route(
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.");