!htp Refactor ExceptionHandler infrastructure for symmetry with RejectionHandler

This commit is contained in:
Mathias 2015-02-26 15:47:39 +01:00
parent 9c3124f344
commit 7510ec80a4
3 changed files with 19 additions and 14 deletions

View file

@ -126,11 +126,7 @@ trait RouteTest extends RequestBuilding with RouteTestResultComponent with Marsh
securedConnection = defaultHostInfo.securedConnection,
defaultHostHeader = defaultHostInfo.host)
val ctx = new RequestContextImpl(effectiveRequest, setup.routingLog.requestLog(effectiveRequest), setup.settings)
val sealedExceptionHandler = {
import setup._
if (exceptionHandler.isDefault) exceptionHandler
else exceptionHandler orElse ExceptionHandler.default(settings)(setup.executionContext)
}
val sealedExceptionHandler = setup.exceptionHandler.seal(setup.settings)(setup.executionContext)
val semiSealedRoute = // sealed for exceptions but not for rejections
Directives.handleExceptions(sealedExceptionHandler) { route }
val deferrableRouteResult = semiSealedRoute(ctx)

View file

@ -10,23 +10,35 @@ import akka.http.model._
import StatusCodes._
trait ExceptionHandler extends ExceptionHandler.PF {
def isDefault: Boolean
/**
* Creates a new [[ExceptionHandler]] which uses the given one as fallback for this one.
*/
def withFallback(that: ExceptionHandler): ExceptionHandler
/**
* "Seals" this handler by attaching a default handler as fallback if necessary.
*/
def seal(settings: RoutingSettings)(implicit ec: ExecutionContext): ExceptionHandler
}
object ExceptionHandler {
type PF = PartialFunction[Throwable, Route]
implicit def apply(pf: PF): ExceptionHandler = apply(default = false)(pf)
implicit def apply(pf: PF): ExceptionHandler = apply(knownToBeSealed = false)(pf)
private def apply(default: Boolean)(pf: PF): ExceptionHandler =
private def apply(knownToBeSealed: Boolean)(pf: PF): ExceptionHandler =
new ExceptionHandler {
def isDefault: Boolean = default
def isDefinedAt(error: Throwable) = pf.isDefinedAt(error)
def apply(error: Throwable) = pf(error)
def withFallback(that: ExceptionHandler): ExceptionHandler =
if (!knownToBeSealed) ExceptionHandler(knownToBeSealed = false)(this orElse that) else this
def seal(settings: RoutingSettings)(implicit ec: ExecutionContext): ExceptionHandler =
if (!knownToBeSealed) ExceptionHandler(knownToBeSealed = true)(this orElse default(settings)) else this
}
def default(settings: RoutingSettings)(implicit ec: ExecutionContext): ExceptionHandler =
apply(default = true) {
apply(knownToBeSealed = true) {
case IllegalRequestException(info, status) ctx {
ctx.log.warning("Illegal request {}\n\t{}\n\tCompleting with '{}' response",
ctx.request, info.formatPretty, status)

View file

@ -22,10 +22,7 @@ object Route {
def seal(route: Route)(implicit setup: RoutingSetup): Route = {
import directives.ExecutionDirectives._
import setup._
val sealedExceptionHandler =
if (exceptionHandler.isDefault) exceptionHandler
else exceptionHandler orElse ExceptionHandler.default(settings)
handleExceptions(sealedExceptionHandler) {
handleExceptions(exceptionHandler.seal(settings)) {
handleRejections(rejectionHandler.seal) {
route
}