diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 9daee01172..ab1d331da9 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -59,7 +59,7 @@ The Akka build includes a special task called `validatePullRequest` which invest
then running tests only on those projects.
For example changing something in `akka-http-core` would cause tests to be run in all projects which depend on it
-(e.g. `akka-http-core-tests`, `akka-http-marshallers-*`, `akka-docs` etc.).
+(e.g. `akka-http-tests`, `akka-http-marshallers-*`, `akka-docs` etc.).
To use the task simply type, and the output should include entries like shown below:
diff --git a/akka-http-tests/src/test/scala/akka/http/scaladsl/server/directives/MarshallingDirectivesSpec.scala b/akka-http-tests/src/test/scala/akka/http/scaladsl/server/directives/MarshallingDirectivesSpec.scala
index 8f4a894853..50be2b4c58 100644
--- a/akka-http-tests/src/test/scala/akka/http/scaladsl/server/directives/MarshallingDirectivesSpec.scala
+++ b/akka-http-tests/src/test/scala/akka/http/scaladsl/server/directives/MarshallingDirectivesSpec.scala
@@ -16,6 +16,9 @@ import spray.json.DefaultJsonProtocol._
import MediaTypes._
import HttpCharsets._
import headers._
+import org.xml.sax.SAXParseException
+
+import scala.util.{ Failure, Try }
class MarshallingDirectivesSpec extends RoutingSpec with Inside {
import ScalaXmlSupport._
@@ -26,6 +29,12 @@ class MarshallingDirectivesSpec extends RoutingSpec with Inside {
case NodeSeq.Empty ⇒ throw Unmarshaller.NoContentException
case x ⇒ { val i = x.text.toInt; require(i >= 0); i }
}
+ implicit val TryIntUnmarshaller: FromEntityUnmarshaller[Try[Int]] =
+ IntUnmarshaller map {
+ Try(_).recoverWith {
+ case e: IllegalArgumentException ⇒ Failure(RejectionError(ValidationRejection(e.getMessage, Option(e))))
+ }
+ }
val `text/xxml` = MediaType.customWithFixedCharset("text", "xxml", `UTF-8`)
implicit val IntMarshaller: ToEntityMarshaller[Int] =
@@ -71,12 +80,23 @@ class MarshallingDirectivesSpec extends RoutingSpec with Inside {
}
}
}
+ "unwrap a RejectionError and return its exception" in {
+ Put("/", HttpEntity(ContentType(`text/xml`, iso88592), "-3")) ~> {
+ entity(as[Try[Int]]) { _ ⇒ completeOk }
+ } ~> check {
+ inside(rejection) {
+ case ValidationRejection("requirement failed", Some(_: IllegalArgumentException)) ⇒
+ }
+ }
+ }
"return a MalformedRequestContentRejection if unmarshalling failed due to a not further classified error" in {
Put("/", HttpEntity(ContentTypes.`text/xml(UTF-8)`, " {
entity(as[NodeSeq]) { _ ⇒ completeOk }
} ~> check {
- rejection shouldEqual MalformedRequestContentRejection(
- "XML document structures must start and end within the same entity.", None)
+ inside(rejection) {
+ case MalformedRequestContentRejection(
+ "XML document structures must start and end within the same entity.", _: SAXParseException) ⇒
+ }
}
}
"extract an Option[T] from the requests entity using the in-scope Unmarshaller" in {
diff --git a/akka-http/src/main/scala/akka/http/impl/server/RejectionHandlerWrapper.scala b/akka-http/src/main/scala/akka/http/impl/server/RejectionHandlerWrapper.scala
index 0af39fba4c..0a4fbeaa56 100644
--- a/akka-http/src/main/scala/akka/http/impl/server/RejectionHandlerWrapper.scala
+++ b/akka-http/src/main/scala/akka/http/impl/server/RejectionHandlerWrapper.scala
@@ -48,7 +48,7 @@ private[http] class RejectionHandlerWrapper(javaHandler: server.RejectionHandler
case TooManyRangesRejection(maxRanges) ⇒
handleTooManyRangesRejection(ctx, maxRanges)
case MalformedRequestContentRejection(message, cause) ⇒
- handleMalformedRequestContentRejection(ctx, message, cause.orNull)
+ handleMalformedRequestContentRejection(ctx, message, cause)
case RequestEntityExpectedRejection ⇒
handleRequestEntityExpectedRejection(ctx)
case UnacceptedResponseContentTypeRejection(supported) ⇒
diff --git a/akka-http/src/main/scala/akka/http/scaladsl/server/Rejection.scala b/akka-http/src/main/scala/akka/http/scaladsl/server/Rejection.scala
index f392129914..951cd31ae1 100644
--- a/akka-http/src/main/scala/akka/http/scaladsl/server/Rejection.scala
+++ b/akka-http/src/main/scala/akka/http/scaladsl/server/Rejection.scala
@@ -99,7 +99,7 @@ case class TooManyRangesRejection(maxRanges: Int) extends Rejection
* Note that semantic issues with the request content (e.g. because some parameter was out of range)
* will usually trigger a `ValidationRejection` instead.
*/
-case class MalformedRequestContentRejection(message: String, cause: Option[Throwable] = None) extends Rejection
+case class MalformedRequestContentRejection(message: String, cause: Throwable) extends Rejection
/**
* Rejection created by unmarshallers.
diff --git a/akka-http/src/main/scala/akka/http/scaladsl/server/directives/MarshallingDirectives.scala b/akka-http/src/main/scala/akka/http/scaladsl/server/directives/MarshallingDirectives.scala
index bf0d60e0f3..d887def314 100644
--- a/akka-http/src/main/scala/akka/http/scaladsl/server/directives/MarshallingDirectives.scala
+++ b/akka-http/src/main/scala/akka/http/scaladsl/server/directives/MarshallingDirectives.scala
@@ -33,10 +33,11 @@ trait MarshallingDirectives {
import ctx.materializer
onComplete(um(ctx.request)) flatMap {
case Success(value) ⇒ provide(value)
+ case Failure(RejectionError(r)) ⇒ reject(r)
case Failure(Unmarshaller.NoContentException) ⇒ reject(RequestEntityExpectedRejection)
case Failure(Unmarshaller.UnsupportedContentTypeException(x)) ⇒ reject(UnsupportedRequestContentTypeRejection(x))
case Failure(x: IllegalArgumentException) ⇒ reject(ValidationRejection(x.getMessage.nullAsEmpty, Some(x)))
- case Failure(x) ⇒ reject(MalformedRequestContentRejection(x.getMessage.nullAsEmpty, Option(x.getCause)))
+ case Failure(x) ⇒ reject(MalformedRequestContentRejection(x.getMessage.nullAsEmpty, x))
}
} & cancelRejections(RequestEntityExpectedRejection.getClass, classOf[UnsupportedRequestContentTypeRejection])