diff --git a/akka-http-tests/src/test/scala/akka/http/scaladsl/server/directives/RouteDirectivesSpec.scala b/akka-http-tests/src/test/scala/akka/http/scaladsl/server/directives/RouteDirectivesSpec.scala index fea5a6cf16..09f5bc03f1 100644 --- a/akka-http-tests/src/test/scala/akka/http/scaladsl/server/directives/RouteDirectivesSpec.scala +++ b/akka-http-tests/src/test/scala/akka/http/scaladsl/server/directives/RouteDirectivesSpec.scala @@ -4,9 +4,12 @@ package akka.http.scaladsl.server.directives +import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport +import akka.http.scaladsl.marshallers.xml.ScalaXmlSupport +import akka.stream.scaladsl.Sink import org.scalatest.FreeSpec -import scala.concurrent.Promise +import scala.concurrent.{ Future, Promise } import akka.http.scaladsl.marshallers.xml.ScalaXmlSupport._ import akka.http.scaladsl.marshalling._ import akka.http.scaladsl.server._ @@ -16,6 +19,8 @@ import headers._ import StatusCodes._ import MediaTypes._ +import scala.xml.NodeSeq + class RouteDirectivesSpec extends FreeSpec with GenericRoutingSpec { "The `complete` directive should" - { @@ -57,7 +62,7 @@ class RouteDirectivesSpec extends FreeSpec with GenericRoutingSpec { } } } - "allow easy handling of futured ToResponseMarshallers" in pending /*{ + "allow easy handling of futured ToResponseMarshallers" in { trait RegistrationStatus case class Registered(name: String) extends RegistrationStatus case object AlreadyRegistered extends RegistrationStatus @@ -76,8 +81,8 @@ class RouteDirectivesSpec extends FreeSpec with GenericRoutingSpec { case Registered(_) ⇒ HttpEntity.Empty case AlreadyRegistered ⇒ import spray.json.DefaultJsonProtocol._ - import spray.httpx.SprayJsonSupport._ - (StatusCodes.BadRequest, Map("error" -> "User already Registered")) + import SprayJsonSupport._ + StatusCodes.BadRequest -> Map("error" -> "User already Registered") } } } @@ -88,10 +93,10 @@ class RouteDirectivesSpec extends FreeSpec with GenericRoutingSpec { } Get("/register/karl") ~> route ~> check { status shouldEqual StatusCodes.OK - entity shouldEqual HttpEntity.Empty + responseAs[String] shouldEqual "" } - }*/ - "do Content-Type negotiation for multi-marshallers" in pendingUntilFixed { + } + "do Content-Type negotiation for multi-marshallers" in { val route = get & complete(Data("Ida", 83)) import akka.http.scaladsl.model.headers.Accept @@ -105,10 +110,9 @@ class RouteDirectivesSpec extends FreeSpec with GenericRoutingSpec { Get().withHeaders(Accept(MediaTypes.`text/xml`)) ~> route ~> check { responseAs[xml.NodeSeq] shouldEqual Ida83 } - pending - /*Get().withHeaders(Accept(MediaTypes.`text/plain`)) ~> HttpService.sealRoute(route) ~> check { + Get().withHeaders(Accept(MediaTypes.`text/plain`)) ~> Route.seal(route) ~> check { status shouldEqual StatusCodes.NotAcceptable - }*/ + } } } @@ -133,16 +137,17 @@ class RouteDirectivesSpec extends FreeSpec with GenericRoutingSpec { case class Data(name: String, age: Int) object Data { - //import spray.json.DefaultJsonProtocol._ - //import spray.httpx.SprayJsonSupport._ + import spray.json.DefaultJsonProtocol._ + import SprayJsonSupport._ + import ScalaXmlSupport._ - val jsonMarshaller: ToEntityMarshaller[Data] = FIXME // jsonFormat2(Data.apply) - val xmlMarshaller: ToEntityMarshaller[Data] = FIXME - /*Marshaller.delegate[Data, xml.NodeSeq](MediaTypes.`text/xml`) { (data: Data) ⇒ - { data.name }{ data.age } - }*/ + val jsonMarshaller: ToEntityMarshaller[Data] = jsonFormat2(Data.apply) - implicit val dataMarshaller: ToResponseMarshaller[Data] = FIXME - //ToResponseMarshaller.oneOf(MediaTypes.`application/json`, MediaTypes.`text/xml`)(jsonMarshaller, xmlMarshaller) + val xmlMarshaller: ToEntityMarshaller[Data] = Marshaller.combined { (data: Data) ⇒ + { data.name }{ data.age } + } + + implicit val dataMarshaller: ToResponseMarshaller[Data] = + Marshaller.oneOf(jsonMarshaller, xmlMarshaller) } } diff --git a/akka-http/src/main/scala/akka/http/scaladsl/marshalling/Marshaller.scala b/akka-http/src/main/scala/akka/http/scaladsl/marshalling/Marshaller.scala index 6d8e930786..008a35200d 100644 --- a/akka-http/src/main/scala/akka/http/scaladsl/marshalling/Marshaller.scala +++ b/akka-http/src/main/scala/akka/http/scaladsl/marshalling/Marshaller.scala @@ -117,6 +117,13 @@ object Marshaller */ def opaque[A, B](marshal: A ⇒ B): Marshaller[A, B] = strict { value ⇒ Marshalling.Opaque(() ⇒ marshal(value)) } + + /** + * Helper for creating a [[Marshaller]] combined of the provided `marshal` function + * and an implicit Marshaller which is able to produce the required final type. + */ + def combined[A, B, C](marshal: A ⇒ B)(implicit m2: Marshaller[B, C]): Marshaller[A, C] = + Marshaller[A, C] { ec ⇒ a ⇒ m2.compose(marshal).apply(a)(ec) } } //#