=htp #15792 make entityAs directive turn IllegalArgumentException into ValidationRejection
This commit is contained in:
parent
37aa2cb886
commit
612fc052e6
3 changed files with 28 additions and 4 deletions
|
|
@ -6,6 +6,7 @@ package akka.http.server
|
|||
package directives
|
||||
|
||||
import scala.xml.NodeSeq
|
||||
import org.scalatest.Inside
|
||||
import akka.http.marshallers.xml.ScalaXmlSupport
|
||||
import akka.http.unmarshalling._
|
||||
import akka.http.marshalling._
|
||||
|
|
@ -16,14 +17,14 @@ import HttpCharsets._
|
|||
import headers._
|
||||
import spray.json.DefaultJsonProtocol._
|
||||
|
||||
class MarshallingDirectivesSpec extends RoutingSpec {
|
||||
class MarshallingDirectivesSpec extends RoutingSpec with Inside {
|
||||
import ScalaXmlSupport._
|
||||
|
||||
private val iso88592 = HttpCharsets.getForKey("iso-8859-2").get
|
||||
implicit val IntUnmarshaller: FromEntityUnmarshaller[Int] =
|
||||
nodeSeqUnmarshaller(ContentTypeRange(`text/xml`, iso88592), `text/html`) map {
|
||||
case NodeSeq.Empty ⇒ throw Unmarshaller.NoContentException
|
||||
case x ⇒ x.text.toInt
|
||||
case x ⇒ { val i = x.text.toInt; require(i >= 0); i }
|
||||
}
|
||||
|
||||
implicit val IntMarshaller: ToEntityMarshaller[Int] =
|
||||
|
|
@ -60,6 +61,23 @@ class MarshallingDirectivesSpec extends RoutingSpec {
|
|||
entity(as[String]) { _ ⇒ validate(false, "Problem") { completeOk } }
|
||||
} ~> check { rejection shouldEqual ValidationRejection("Problem") }
|
||||
}
|
||||
"return a ValidationRejection if the request entity is semantically invalid (IllegalArgumentException)" in {
|
||||
Put("/", HttpEntity(ContentType(`text/xml`, iso88592), "<int>-3</int>")) ~> {
|
||||
entity(as[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(`text/xml`, "<foo attr='illegal xml'")) ~> {
|
||||
entity(as[NodeSeq]) { _ ⇒ completeOk }
|
||||
} ~> check {
|
||||
rejection shouldEqual MalformedRequestContentRejection(
|
||||
"XML document structures must start and end within the same entity.", None)
|
||||
}
|
||||
}
|
||||
"extract an Option[T] from the requests entity using the in-scope Unmarshaller" in {
|
||||
Put("/", <p>cool</p>) ~> {
|
||||
entity(as[Option[NodeSeq]]) { echoComplete }
|
||||
|
|
|
|||
|
|
@ -94,7 +94,10 @@ case class TooManyRangesRejection(maxRanges: Int) extends Rejection
|
|||
|
||||
/**
|
||||
* Rejection created by unmarshallers.
|
||||
* Signals that the request was rejected because there was an error while unmarshalling the request content
|
||||
* Signals that the request was rejected because unmarshalling failed with an error that wasn't
|
||||
* an `IllegalArgumentException`. Usually that means that the request content was not of the expected format.
|
||||
* 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
|
||||
|
||||
|
|
@ -161,7 +164,9 @@ case object AuthorizationFailedRejection extends Rejection
|
|||
case class MissingCookieRejection(cookieName: String) extends Rejection
|
||||
|
||||
/**
|
||||
* Rejection created by the `validation` directive.
|
||||
* Rejection created by the `validation` directive as well as for `IllegalArgumentExceptions`
|
||||
* thrown by domain model constructors (e.g. via `require`).
|
||||
* It signals that an expected value was semantically invalid.
|
||||
*/
|
||||
case class ValidationRejection(message: String, cause: Option[Throwable] = None) extends Rejection
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ trait MarshallingDirectives {
|
|||
case Success(value) ⇒ provide(value)
|
||||
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)))
|
||||
}
|
||||
} & cancelRejections(RequestEntityExpectedRejection.getClass, classOf[UnsupportedRequestContentTypeRejection])
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue