如何递归处理 Akka HTTP 路由

How to handle an Akka HTTP route recursively

我有一个场景,其中路线包含 key/value 对的交替段。对的数量未定义,收集这些对的有效方法是什么。例如,路线可能看起来像

/key1/value1/key2/value2/key3/value3

我想得到一个链接图

(key1, value1) -> (key2, value2) -> (key3, value3)

我知道我们可以获取路径段列表并按上述方式进行转换。但我正在寻找的是像

这样的导航路径
class EntitiesSpec extends WordSpec with Matchers with ScalatestRouteTest with Directives {

  def lastSegment:Directive1[String] = path(Segment)
  def intermediate: Directive1[String] = <processing the intermediate>

  val navigate = (intermediate & navigate) ~ lastSegment
  val route = navigate { (param1:String) =>
    complete(param1)
  }

  "this should call the route" should {
    "invoke a route /hello" in {
      Get("/hello/world/hello1/world1/hello3/world3") ~> route ~> check {
        println(responseAs[String])
      }
    }
  }
}

另一个好的方法是,例如,如果你有一条像

这样的路径
/12/1/5/6/8

如何定义可以递归相加的指令?感谢任何帮助。

不要为 Key/Value 对使用路径

问题中描述的方法是一种反模式。 Key/value 配对可以在 query string. By using the parameterMap 指令中更容易完成,将 key/value 对转换为 String 元组列表变得微不足道:

//matches a uri of the form: /?key1=value1&key2=value2
val queryStringRoute = 
  parameterMap { params =>
    val linkedPairList : List[(String, String)] = params.toList
  }

不要对指令使用递归

递归指令也是不明智的。 A Route is declared as a simple Function1:

type Route = (RequestContext) ⇒ Future[RouteResult]

因为 return 类型是 Future 那么任何递归都必须是对原始 Future 的操作。因此,原始调用栈不能被忽略,递归永远不会尾部优化。如果 Path 足够长,可能会导致递归函数的计算溢出。

如果必须使用路径

当你别无选择只能使用 Path 那么你可以做一些 String 解析:

val pathToKeyValuePairs : Uri.Path => List[(String, String)] =
  (_ : Uri.Path)
    .toString
    .split('/')
    .grouped(2)
    .map(arr => arr(0) -> arr(1))
    .toList

现在可以在 Route:

中使用此解析器
val unadvisedRoute = 
  extractRequest { request =>
    val linkedPairList : List[(String, String)] = 
      pathToKeyValuePairs(request.uri.path)
  }