我想在Spray路由不區分大小寫的情況下進行參數解析。例如:噴霧路由中的大小寫不敏感參數解析
在這條路徑中,我希望pageSize和appId參數在不區分大小寫的情況下工作。例如,pagesize = 5或PAGESIZE = 5。
我想在Spray路由不區分大小寫的情況下進行參數解析。例如:噴霧路由中的大小寫不敏感參數解析
在這條路徑中,我希望pageSize和appId參數在不區分大小寫的情況下工作。例如,pagesize = 5或PAGESIZE = 5。
看起來像從URI邏輯獲取查詢參數在ParamDefMagnet2.filter函數中硬編碼。
爲了克服這個限制,我會複製該代碼,用ctx.request.uri.query.find(_._1.equalsIgnoreCase(paramName))
代替邏輯並在需要時導入它。
使用例子是這樣的:
import CaseInsensitiveQueryParameters._
val route: Route = {
(path("search") & get) {
parameters('pagesize.as[Int] ?, 'appId ?) { (pageSize, appId) =>
...
}
}
}
而改變implicits應該是這樣的:
object CaseInsensitiveQueryParameters {
type ParamDefMagnetAux[A, B] = ParamDefMagnet2[A] { type Out = B }
def ParamDefMagnetAux[A, B](f: A ⇒ B) = new ParamDefMagnet2[A] { type Out = B; def apply(value: A) = f(value) }
import spray.httpx.unmarshalling.{ FromStringOptionDeserializer ⇒ FSOD, _ }
import BasicDirectives._
import RouteDirectives._
/************ "regular" parameter extraction ******************/
private def extractParameter[A, B](f: A ⇒ Directive1[B]) = ParamDefMagnetAux[A, Directive1[B]](f)
private def filter[T](paramName: String, fsod: FSOD[T]): Directive1[T] =
extract(ctx ⇒ fsod(ctx.request.uri.query.find(_._1.equalsIgnoreCase(paramName)))).flatMap {
case Right(x) ⇒ provide(x)
case Left(ContentExpected) ⇒ reject(MissingQueryParamRejection(paramName))
case Left(MalformedContent(error, cause)) ⇒ reject(MalformedQueryParamRejection(paramName, error, cause))
case Left(x: UnsupportedContentType) ⇒ throw new IllegalStateException(x.toString)
}
implicit def forString(implicit fsod: FSOD[String]) = extractParameter[String, String] { string ⇒
filter(string, fsod)
}
implicit def forSymbol(implicit fsod: FSOD[String]) = extractParameter[Symbol, String] { symbol ⇒
filter(symbol.name, fsod)
}
implicit def forNDesR[T] = extractParameter[NameDeserializerReceptacle[T], T] { nr ⇒
filter(nr.name, nr.deserializer)
}
implicit def forNDefR[T](implicit fsod: FSOD[T]) = extractParameter[NameDefaultReceptacle[T], T] { nr ⇒
filter(nr.name, fsod.withDefaultValue(nr.default))
}
implicit def forNDesDefR[T] = extractParameter[NameDeserializerDefaultReceptacle[T], T] { nr ⇒
filter(nr.name, nr.deserializer.withDefaultValue(nr.default))
}
implicit def forNR[T](implicit fsod: FSOD[T]) = extractParameter[NameReceptacle[T], T] { nr ⇒
filter(nr.name, fsod)
}
}
我把穆斯塔法的回答一步,擴展參數語法,所以你可以使用非-case敏感參數連同區分大小寫(Big Hooray for typeclasses和magnet pattern!):
package caseinsensitive
import spray.routing.SimpleRoutingApp
import akka.actor.ActorSystem
import spray.routing.directives.BasicDirectives
import spray.routing.directives.RouteDirectives
import scala.language.implicitConversions
/**/
import spray.httpx.unmarshalling.{ FromStringOptionDeserializer ⇒ FSOD, _}
trait ToCINameReceptaclePimps {
implicit def symbol2CINR(symbol: Symbol) = new CINameReceptacleHelper[String](symbol.name)
implicit def string2CINR(string: String) = new CINameReceptacleHelper[String](string)
}
case class CINameReceptacleHelper[T](name: String) {
def insensitive = CINameReceptacle[T](name)
}
case class CINameReceptacle[A](name: String) {
def as[B] = CINameReceptacle[B](name)
def as[B](deserializer: FSOD[B]) = CINameDeserializerReceptacle(name, deserializer)
def ? = as[Option[A]]
def ?[B](default: B) =CINameDefaultReceptacle(name, default)
def ![B](requiredValue: B) = CIRequiredValueReceptacle(name, requiredValue)
}
case class CINameDeserializerReceptacle[A](name: String, deserializer: FSOD[A]) {
def ? = CINameDeserializerReceptacle(name, Deserializer.liftToTargetOption(deserializer))
def ?(default: A) = CINameDeserializerDefaultReceptacle(name, deserializer, default)
def !(requiredValue: A) = CIRequiredValueDeserializerReceptacle(name, deserializer, requiredValue)
}
case class CINameDefaultReceptacle[A](name: String, default: A)
case class CIRequiredValueReceptacle[A](name: String, requiredValue: A)
case class CINameDeserializerDefaultReceptacle[A](name: String, deserializer: FSOD[A], default: A)
case class CIRequiredValueDeserializerReceptacle[A](name: String, deserializer: FSOD[A], requiredValue: A)
/**/
trait CaseInsensitiveParams extends ToCINameReceptaclePimps {
import spray.routing._
import spray.routing.directives._
import spray.httpx.unmarshalling.{ FromStringOptionDeserializer ⇒ FSOD, _ }
import BasicDirectives._
import RouteDirectives._
type ParamDefMagnetAux[A, B] = ParamDefMagnet2[A] { type Out = B }
def ParamDefMagnetAux[A, B](f: A ⇒ B) = new ParamDefMagnet2[A] { type Out = B; def apply(value: A) = f(value) }
private def extractParameter[A, B](f: A ⇒ Directive1[B]) = ParamDefMagnetAux[A, Directive1[B]](f)
private def filterCI[T](paramName: String, fsod: FSOD[T]): Directive1[T] =
extract(ctx ⇒ fsod(ctx.request.uri.query.find(_._1.equalsIgnoreCase(paramName)).map(_._2))).flatMap {
case Right(x) ⇒ provide(x)
case Left(ContentExpected) ⇒ reject(MissingQueryParamRejection(paramName))
case Left(MalformedContent(error, cause)) ⇒ reject(MalformedQueryParamRejection(paramName, error, cause))
case Left(x: UnsupportedContentType) ⇒ throw new IllegalStateException(x.toString)
}
/************ "regular" parameter extraction ******************/
implicit def forCINDesR[T] = extractParameter[CINameDeserializerReceptacle[T], T] { nr ⇒
filterCI(nr.name, nr.deserializer)
}
implicit def forCINDefR[T](implicit fsod: FSOD[T]) = extractParameter[CINameDefaultReceptacle[T], T] { nr ⇒
filterCI(nr.name, fsod.withDefaultValue(nr.default))
}
implicit def forCINDesDefR[T] = extractParameter[CINameDeserializerDefaultReceptacle[T], T] { nr ⇒
filterCI(nr.name, nr.deserializer.withDefaultValue(nr.default))
}
implicit def forCINR[T](implicit fsod: FSOD[T]) = extractParameter[CINameReceptacle[T], T] { nr ⇒
filterCI(nr.name, fsod)
}
/************ required parameter support ******************/
private def requiredFilterCI(paramName: String, fsod: FSOD[_], requiredValue: Any): Directive0 =
extract(ctx ⇒ fsod(ctx.request.uri.query.find(_._1.equalsIgnoreCase(paramName)).map(_._2))).flatMap {
case Right(value) if value == requiredValue ⇒ pass
case _ ⇒ reject
}
implicit def forCIRVR[T](implicit fsod: FSOD[T]) = ParamDefMagnetAux[CIRequiredValueReceptacle[T], Directive0] { rvr ⇒
requiredFilterCI(rvr.name, fsod, rvr.requiredValue)
}
implicit def forCIRVDR[T] = ParamDefMagnetAux[CIRequiredValueDeserializerReceptacle[T], Directive0] { rvr ⇒
requiredFilterCI(rvr.name, rvr.deserializer, rvr.requiredValue)
}
}
object Main extends App with SimpleRoutingApp with CaseInsensitiveParams {
implicit val system = ActorSystem("my-system")
startServer(interface = "localhost", port = 8080) {
path("hello") {
parameters("foo".insensitive.?) { foo =>
get {
complete {
<h1>You said {foo} </h1>
}
}
}
}
}
}
如果您不需要所有這些,則可以使用parameterMap
指令並從中獲取參數。
您可以創建一個自定義指令來代替參數。我現在不在計算機上,但通過查看參數的實現不應該很難。 –