forked from scalatra/scalatra
/
routeMatcher.scala
64 lines (50 loc) · 1.73 KB
/
routeMatcher.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
package org.scalatra
import scala.util.matching.Regex
import util.MultiMap
trait RouteMatcher
{
def apply(): Option[ScalatraKernel.MultiParams]
}
trait ReversibleRouteMatcher
{
def reverse(params: Map[String, String], splats: List[String]): String
}
final class SinatraRouteMatcher(path: String, requestPath: => String)
extends RouteMatcher with ReversibleRouteMatcher
{
def apply() = SinatraPathPatternParser(path)(requestPath)
def reverse(params: Map[String, String], splats: List[String]): String =
replaceSplats(replaceNamedParams(params), splats)
private def replaceNamedParams(params: Map[String, String]) =
""":[^/?#\.]+""".r replaceAllIn (path, s =>
params.get(s.toString.tail) match {
case Some(value) => value
case None => throw new Exception("The url \"%s\" requires param \"%s\"" format (path, s))
})
private def replaceSplats(slug: String, splats: List[String]): String =
splats match {
case Nil => slug
case s :: rest => replaceSplats("""\*""".r replaceFirstIn (slug, s), rest)
}
override def toString = path
}
final class PathPatternRouteMatcher(pattern: PathPattern, requestPath: => String)
extends RouteMatcher
{
def apply() = pattern(requestPath)
override def toString = pattern.regex.toString
}
final class RegexRouteMatcher(regex: Regex, requestPath: => String)
extends RouteMatcher
{
def apply() = regex.findFirstMatchIn(requestPath) map { _.subgroups match {
case Nil => MultiMap()
case xs => Map("captures" -> xs)
}}
override def toString = regex.toString
}
final class BooleanBlockRouteMatcher(block: => Boolean) extends RouteMatcher
{
def apply() = if (block) Some(MultiMap()) else None
override def toString = "[Boolean Guard]"
}