From 7510ec80a4395fd2e9756a20c2ef95ff68e8daaa Mon Sep 17 00:00:00 2001 From: Mathias Date: Thu, 26 Feb 2015 15:47:39 +0100 Subject: [PATCH] !htp Refactor ExceptionHandler infrastructure for symmetry with RejectionHandler --- .../scala/akka/http/testkit/RouteTest.scala | 6 +---- .../akka/http/server/ExceptionHandler.scala | 22 ++++++++++++++----- .../main/scala/akka/http/server/Route.scala | 5 +---- 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/akka-http-testkit/src/main/scala/akka/http/testkit/RouteTest.scala b/akka-http-testkit/src/main/scala/akka/http/testkit/RouteTest.scala index 3ec2b3f445..3e08df9201 100644 --- a/akka-http-testkit/src/main/scala/akka/http/testkit/RouteTest.scala +++ b/akka-http-testkit/src/main/scala/akka/http/testkit/RouteTest.scala @@ -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) diff --git a/akka-http/src/main/scala/akka/http/server/ExceptionHandler.scala b/akka-http/src/main/scala/akka/http/server/ExceptionHandler.scala index f34f367154..130cd9b8bc 100644 --- a/akka-http/src/main/scala/akka/http/server/ExceptionHandler.scala +++ b/akka-http/src/main/scala/akka/http/server/ExceptionHandler.scala @@ -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) diff --git a/akka-http/src/main/scala/akka/http/server/Route.scala b/akka-http/src/main/scala/akka/http/server/Route.scala index 2a155a6870..601a6fb08a 100644 --- a/akka-http/src/main/scala/akka/http/server/Route.scala +++ b/akka-http/src/main/scala/akka/http/server/Route.scala @@ -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 }