2013-10-25 38 views
1

我有,我想在多個方案中重用的路線片段:我在哪裏可以指定dirSegment val的值如何創建自定義指令來重用路由?

val dirSegment = "licenses" 
path(dirSegment ~ PathEnd) { 
    redirect(dirSegment + "/", StatusCodes.MovedPermanently) 
} ~ 
pathPrefix(dirSegment) { 
    path("") { 
    /* do something */ 
    } 
} 

我想轉這一個指令(或參數化路線?)和代替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?

回答

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/看「這是/約/」。嵌套路徑ab按預期工作(即沒有自己的重定向)。

注意:此解決方案適用於Spray 1.2。

+1

我們在RC1中改變了一下PathMatcher行爲,並且在最終版本發佈之前可能會再做一次。從RC1開始,有'rawPathPrefix'完全匹配而不接受任何可選的結尾斜線。有了這個,你應該可以編寫'rawPathPrefix(Slash〜segment〜PathEnd)'來匹配沒有斜槓。否則,這看起來不錯。 – jrudolph

+0

@jrudolph,除非PathEnd已經改變,是不是還會匹配一個可選的結尾斜槓?我記得嘗試各種方法(可能'rawPathPrefix'),並有重定向循環的問題,直到我寫我自己的'PathEndNoSlash'。 – Andy

+1

下面是我今天下午寫的遷移指南中的PR,它有望解釋新的行爲:https://github.com/spray/spray/pull/659/files – jrudolph

相關問題