我有一个我希望在多种情况下重复使用的路由片段:
val dirSegment = "licenses"
path( dirSegment ~ PathEnd ) {
redirect( dirSegment + "/", StatusCodes.MovedPermanently )
} ~
pathPrefix(dirSegment) {
path("") {
/* do something */
}
}
我想将其转换为指令(或可参数化的路由?),其中我可以指定dirSegment
val的值以及任意进一步的路由/代码来代替path("") { /* do something */ }
白色保留重定向行为,如下所示:
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 */
}
}
请注意,此问题的灵感来自于How do I automatically add slash to end of a url in spray routing?
中的一些讨论答案 0 :(得分:2)
您需要为此编写自定义指令。
// 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/
并看到“这是/关于/”。嵌套路径a
和b
按预期工作(即,没有自己的重定向)。
注意:此解决方案适用于Spray 1.2。