You'll need to write a custom directive for this.
// additional imports you may need
import shapeless.HNil
import spray.http.StatusCodes
import spray.routing.Directive0
import spray.routing.PathMatcher
Now that that's out of the way:
/**
* 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)
}
Usage:
directoryPath("about") {
path("a") {
complete {
"this is /about/a"
}
} ~ path("b") {
complete {
"this is /about/b"
}
} ~ path(PathEnd) {
complete {
"this is /about/"
}
}
}
If a user accesses /about
, they will be forwarded to /about/
and see "this is /about/". The nested paths a
and b
work as expected (that is, without redirects of their own).
Note: This solution is for Spray 1.2.