Scala 如何创建自定义指令以重用路由?
我有一个要在多个场景中重用的路由片段:Scala 如何创建自定义指令以重用路由?,scala,spray,Scala,Spray,我有一个要在多个场景中重用的路由片段: val dirSegment = "licenses" path( dirSegment ~ PathEnd ) { redirect( dirSegment + "/", StatusCodes.MovedPermanently ) } ~ pathPrefix(dirSegment) { path("") { /* do something */ } } 我想将此转换为一个指令(或可参数化路由?),在该指令中,我可以指定di
val dirSegment = "licenses"
path( dirSegment ~ PathEnd ) {
redirect( dirSegment + "/", StatusCodes.MovedPermanently )
} ~
pathPrefix(dirSegment) {
path("") {
/* do something */
}
}
我想将此转换为一个指令(或可参数化路由?),在该指令中,我可以指定dirSegment
val的值和任意进一步的路由/code,以代替path(“”{/*dosomething*/}
white,保留重定向行为,如下所示:
directoryPath("licenses") {
path("") {
/* do something */
}
} ~
directoryPath("about") {
path("") {
/* do somthing else */
}
}
然而,在不重复的情况下,其行为与以下行为相同:
val dirSegment = "licenses"
val anotherDir = "About"
path( dirSegment ~ PathEnd ) {
redirect(dirSegment + "/", StatusCodes.MovedPermanently )
} ~
pathPrefix(dirSegment) {
path("") {
/* do something */
}
} ~
path( anotherDir ~ PathEnd ) {
redirect(anotherDir + "/", StatusCodes.MovedPermanently )
} ~
pathPrefix(anotherDir) {
path("") {
/* do something else */
}
}
请注意,这个问题的灵感来自于中的一些讨论。您需要为此编写一个自定义指令
// additional imports you may need
import shapeless.HNil
import spray.http.StatusCodes
import spray.routing.Directive0
import spray.routing.PathMatcher
现在,这已经不成问题了:
/**
* Spray's PathEnd matches trailing optional slashes... we can't have that
* otherwise it will cause a redirect loop.
*/
object PathEndNoSlash extends PathMatcher[HNil] {
def apply(path: Path) = path match {
case Path.Empty ⇒ PathMatcher.Matched.Empty
case _ ⇒ PathMatcher.Unmatched
}
}
/**
* Custom directive that uses a redirect to add a trailing slashe to segment
* if the slash isn't present.
*/
def directoryPath(segment: String) = new Directive0 {
def happly(f: HNil ⇒ Route) =
// first, the redirect
pathPrefix(segment ~ PathEndNoSlash) {
redirect("/" + segment + "/", StatusCodes.MovedPermanently) } ~
// delegate actual work to nested directives
pathPrefix(segment).happly(f)
}
用法:
directoryPath("about") {
path("a") {
complete {
"this is /about/a"
}
} ~ path("b") {
complete {
"this is /about/b"
}
} ~ path(PathEnd) {
complete {
"this is /about/"
}
}
}
如果用户访问/about
,他们将被转发到/about/
,并查看“这是/about/”。嵌套路径a
和b
按预期工作(即,没有自己的重定向)
注意:此解决方案适用于Spray 1.2。我们在RC1中稍微更改了PathMatcher行为,可能会在最终版本之前再次更改。从RC1开始,有一个
rawPathPrefix
,它完全匹配,不接受任何可选的尾部斜杠。有了它,您应该能够编写rawPathPrefix(Slash~segment~PathEnd)
来匹配,而不需要斜杠。否则,这看起来不错。@jrudolph,除非PathEnd已更改,否则它不会仍然匹配可选的尾部斜杠吗?我记得我尝试过各种方法(可能是rawPathPrefix
),在编写自己的PathEndNoFlash
之前遇到重定向循环问题。下面是我今天下午编写的迁移指南的PR,希望它能解释新的行为:@Andy我做了一个快速测试-你也可以通过(!)删除PathEndNoFlash对象不要用斜线划<代码>路径前缀(段~!斜杠)