Skip to content

Commit

Permalink
= spray-routing: fix issue #981
Browse files Browse the repository at this point in the history
= spray-routing-tests: add additional test cases for issue #981
  • Loading branch information
mikemckibben committed Dec 24, 2014
1 parent 77addba commit 329dd64
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 42 deletions.
Expand Up @@ -69,6 +69,28 @@ class AnyParamDirectivesSpec extends RoutingSpec {
}
}

"when used with a single parameter with default value" should {
val route = anyParam("x" ? "default") { echoComplete }

"extract the parameter from query parameters" in {
Get("/test?x=specified") ~> route ~> check {
responseAs[String] === "specified"
}
}

"extract the parameter from form" in {
Post("/test", FormData(Map("x" -> "specified"))) ~> route ~> check {
responseAs[String] === "specified"
}
}

"extract default parameter value" in {
Get("/test") ~> route ~> check {
responseAs[String] === "default"
}
}
}

"when used with two required parameters" should {
val route = (path("test") & anyParam("x", "y")) { echoComplete2 }

Expand Down
Expand Up @@ -45,28 +45,11 @@ trait AnyParamDefMagnet {
}

object AnyParamDefMagnet {
private type APDM2Tuple1[T] = AnyParamDefMagnet2[Tuple1[T]]

private def apply[T](value: T)(implicit apdm2Tuple1: APDM2Tuple1[T]) =
implicit def apply[T](value: T)(implicit apdm2: AnyParamDefMagnet2[T]) =
new AnyParamDefMagnet {
type Out = apdm2Tuple1.Out
def apply() = apdm2Tuple1(Tuple1(value))
}

implicit def forString[T <: String](value: T)(implicit apdm2: APDM2Tuple1[T]) = apply(value)
implicit def forSymbol[T <: Symbol](value: T)(implicit apdm2: APDM2Tuple1[T]) = apply(value)
implicit def forNR[T <: NameReceptacle[_]](value: T)(implicit apdm2: APDM2Tuple1[T]) = apply(value)
implicit def forNDesR[T <: NameDeserializerReceptacle[_]](value: T)(implicit apdm2: APDM2Tuple1[T]) = apply(value)
implicit def forNDefR[T <: NameDefaultReceptacle[_]](value: T)(implicit apdm2: APDM2Tuple1[T]) = apply(value)
implicit def forNDesDefR[T <: NameDeserializerDefaultReceptacle[_]](value: T)(implicit apdm2: APDM2Tuple1[T]) = apply(value)

implicit def forRVR[T <: RequiredValueReceptacle[_]](value: T)(implicit apdm2: APDM2Tuple1[T]) = apply(value)
implicit def forRVDR[T <: RequiredValueDeserializerReceptacle[_]](value: T)(implicit apdm2: APDM2Tuple1[T]) = apply(value)

implicit def forTuple[T <: Product](value: T)(implicit apdm21: AnyParamDefMagnet2[T]) =
new AnyParamDefMagnet {
type Out = apdm21.Out
def apply() = apdm21(value)
type Out = apdm2.Out
def apply() = apdm2(value)
}
}

Expand All @@ -79,33 +62,68 @@ object AnyParamDefMagnet2 {
import FieldDefMagnet2.FieldDefMagnetAux
import ParamDefMagnet2.ParamDefMagnetAux

implicit def forTuple[T <: Product, L <: HList, Out](implicit hla: HListerAux[T, L],
apdma: AnyParamDefMagnet2[L]) =
new AnyParamDefMagnet2[T] {
def apply(value: T) = apdma(hla(value))
type Out = apdma.Out
}
type AnyParamDefMagnetAux[A, B] = AnyParamDefMagnet2[A] { type Out = B }
def AnyParamDefMagnetAux[A, B](f: A B) = new AnyParamDefMagnet2[A] { type Out = B; def apply(a: A) = f(a) }

private def extractAnyParam[A, B](f: A Directive1[B]) = AnyParamDefMagnetAux[A, Directive1[B]](f)

private def anyParamWrapper[A, B](a: A)(implicit fdma: FieldDefMagnetAux[A, Directive1[B]], pdma: ParamDefMagnetAux[A, Directive1[B]]): Directive1[B] = {
// handle optional params
// see https://groups.google.com/forum/?fromgroups=#!topic/spray-user/HGEEdVajpUw
fdma(a).hflatMap {
case None :: HNil pdma(a)
case x BasicDirectives.hprovide(x)
} | pdma(a)
}

private def anyParamDefaultWrapper[A, B](a: A, default: B)(implicit fdma: FieldDefMagnetAux[A, Directive1[B]], pdma: ParamDefMagnetAux[A, Directive1[B]]): Directive1[B] =
anyParamWrapper(a).hflatMap {
case None :: HNil BasicDirectives.provide(default)
case x BasicDirectives.hprovide(x)
} | BasicDirectives.provide(default)

implicit def forString(implicit fdma: FieldDefMagnetAux[String, Directive1[String]], pdma: ParamDefMagnetAux[String, Directive1[String]]) = {
extractAnyParam[String, String](anyParamWrapper(_))
}

implicit def forSymbol(implicit fdma: FieldDefMagnetAux[Symbol, Directive1[String]], pdma: ParamDefMagnetAux[Symbol, Directive1[String]]) = {
extractAnyParam[Symbol, String](anyParamWrapper(_))
}

implicit def forNR[T](implicit fdma: FieldDefMagnetAux[NameReceptacle[T], Directive1[T]], pdma: ParamDefMagnetAux[NameReceptacle[T], Directive1[T]]) = {
extractAnyParam[NameReceptacle[T], T](anyParamWrapper(_))
}

implicit def forNDefR[T](implicit fdma: FieldDefMagnetAux[NameReceptacle[T], Directive1[T]], pdma: ParamDefMagnetAux[NameReceptacle[T], Directive1[T]]) = {
extractAnyParam[NameDefaultReceptacle[T], T](t anyParamDefaultWrapper(NameReceptacle[T](t.name), t.default))
}

implicit def forNDesR[T](implicit fdma: FieldDefMagnetAux[NameDeserializerReceptacle[T], Directive1[T]], pdma: ParamDefMagnetAux[NameDeserializerReceptacle[T], Directive1[T]]) = {
extractAnyParam[NameDeserializerReceptacle[T], T](anyParamWrapper(_))
}

implicit def forNDesDefR[T](implicit fdma: FieldDefMagnetAux[NameDeserializerReceptacle[T], Directive1[T]], pdma: ParamDefMagnetAux[NameDeserializerReceptacle[T], Directive1[T]]) = {
extractAnyParam[NameDeserializerDefaultReceptacle[T], T](t anyParamDefaultWrapper(NameDeserializerReceptacle[T](t.name, t.deserializer), t.default))
}

implicit def forRVR[T](implicit fdma: FieldDefMagnetAux[RequiredValueReceptacle[T], Directive1[T]], pdma: ParamDefMagnetAux[RequiredValueReceptacle[T], Directive1[T]]) = {
extractAnyParam[RequiredValueReceptacle[T], T](anyParamWrapper(_))
}

implicit def forRVDR[T](value: T)(implicit fdma: FieldDefMagnetAux[RequiredValueDeserializerReceptacle[T], Directive1[T]], pdma: ParamDefMagnetAux[RequiredValueDeserializerReceptacle[T], Directive1[T]]) = {
extractAnyParam[RequiredValueDeserializerReceptacle[T], T](anyParamWrapper(_))
}

implicit def forTuple[T <: Product, L <: HList, Out0](implicit hla: HListerAux[T, L], pdma: AnyParamDefMagnetAux[L, Out0]) =
AnyParamDefMagnetAux[T, Out0](tuple pdma(hla(tuple)))

implicit def forHList[L <: HList](implicit f: LeftFolder[L, Directive0, MapReduce.type]) =
new AnyParamDefMagnet2[L] {
type Out = f.Out
def apply(value: L) = {
value.foldLeft(BasicDirectives.noop)(MapReduce)
}
}
AnyParamDefMagnetAux[L, f.Out](_.foldLeft(BasicDirectives.noop)(MapReduce))

object MapReduce extends Poly2 {
implicit def from[T, LA <: HList, LB <: HList, Out <: HList](implicit fdma: FieldDefMagnetAux[T, Directive[LB]],
pdma: ParamDefMagnetAux[T, Directive[LB]],
ev: PrependAux[LA, LB, Out]) = {

// see https://groups.google.com/forum/?fromgroups=#!topic/spray-user/HGEEdVajpUw
def fdmaWrapper(t: T): Directive[LB] = fdma(t).hflatMap {
case None :: HNil pdma(t)
case x BasicDirectives.hprovide(x)
}
implicit def from[T, LA <: HList, LB <: HList, Out <: HList](implicit pdma: AnyParamDefMagnetAux[T, Directive[LB]], ev: PrependAux[LA, LB, Out]) =
at[Directive[LA], T] { (a, t) a & pdma(t) }

at[Directive[LA], T] { (a, t) a & (fdmaWrapper(t) | pdma(t)) }
}
}
}

0 comments on commit 329dd64

Please sign in to comment.