How can I programmatically execute Route
of rejection handler and get resulting HttpEntity
?
For example assuming that I have RequestContext
object and Rejection
object I'd like to execute RejectionHandler.default
on it and get HttpEntity
.
Here is example of what I'd like to do:
implicit def myRejectionHandler =
RejectionHandler.newBuilder()
.handleAll[Rejection] { rejections ⇒
def prefixEntity(entity: ResponseEntity): ResponseEntity = entity match {
case HttpEntity.Strict(contentType, data) => {
import spray.json._
val text = ErrorResponse(0, "Rejection", data.utf8String).toJson.prettyPrint
HttpEntity(ContentTypes.`application/json`, text)
}
case _ =>
throw new IllegalStateException("Unexpected entity type")
}
val route: Route = extractRequestContext { ctx =>
mapResponseEntity(prefixEntity) {
// Here I want result of `complete` route from RejectionHandler.default
}
}
route
}
.handleNotFound {
complete((NotFound, "Not here!"))
}
.result()
I think I get the gist of what you want. You can just apply the default rejection handler in there where your comment is. The only thing is that the apply
there returns an Option
that will be None
if the rejections encountered don't hit on anything in that rejection handler. This is unlikely given that you are using the default handler and it pretty much handles everything, but you still need to account for it in the code (hence my getOrElse
that results in a generic InternalServerError
). The modified code would look like this:
val defaultRejectionHandler = RejectionHandler.default
implicit def myRejectionHandler =
RejectionHandler.newBuilder()
.handleAll[Rejection] { rejections ⇒
def prefixEntity(entity: ResponseEntity): ResponseEntity = entity match {
case HttpEntity.Strict(contentType, data) => {
import spray.json._
val text = ErrorResponse(0, "Rejection", data.utf8String).toJson.prettyPrint
HttpEntity(ContentTypes.`application/json`, text)
}
case _ =>
throw new IllegalStateException("Unexpected entity type")
}
val route: Route = extractRequestContext { ctx =>
mapResponseEntity(prefixEntity) {
defaultRejectionHandler.apply(rejections).getOrElse{
complete(StatusCodes.InternalServerError)
}
}
}
route
}
.handleNotFound {
complete((NotFound, "Not here!"))
}
.result()
This compiles, but I did not actually test it to see if we get the desired effect. Also, I didn't need the RequestContext
value ctx
, so you might be able to remove that extractRequestContext
layer in there.