"升降" Scala函数进入HttpRequest处理器

时间:2016-10-01 22:32:03

标签: scala rest type-conversion akka-http

我正在寻找一种转换函数的方法,该函数采用基本参数类型并使用它来处理akka HttpRequest。我希望自动处理Path并将其传递给函数。

举个例子,给出一些功能

def foobar(str : String, i : Int, l : Long) : String = ???

有一种方法可以提升"提升"处理Path的功能。 URL路径示例可以是

  

/ foobar的/爱因斯坦/二千〇一十六分之四十二

提升功能如下所示:

import akka.http.scaladsl.model.Uri.Path
import akka.http.scaladsl.server.Directive

type SomeFunctionType = ???

def lifter(function : SomeFunctionType, path : Path) : Directive = {

  val funcResult = ??? //somehow call function on the Path elements

  complete(funcResult)
}

然后可以按以下方式使用:

val route = 
  get {
    pathPrefix("foobar") {
      extractUnmatchedPath { remainingPath =>
        lifter(foobar, remainingPath)
      }
    }
  }

此提升函数必须遍历函数参数类型,并在将值传递给函数之前将相应的Path部分转换为匹配类型。示例网址将使用调用foobar("enstein", 42, 2016)的结果完成。

无论如何在图书馆中这样做?如果没有,有没有办法定义升降机?

提前感谢您的考虑和回应。

1 个答案:

答案 0 :(得分:1)

您似乎想要创建Route而不是Directive。不同之处在于Route实际处理请求,而Directive包含具有更多功能的路由。您似乎想要最终处理请求,因此它应该是Route

您似乎在寻找一种适用于所有功能的非常通用的解决方案。目前这只是非常困难(甚至不可能),因为你不知何故需要指定如何解析参数。 spray-routing / akka-http路由实际上有点劝阻这种风格,而采用更明确的做事方式。

E.g。给定您(String, Int, Long) => Route的给定函数定义,路径将如下所示:

def foobar(str: String, i: Int, l: Long): Route = complete(s"$str : $i : $l") // example implementation

// usage
path("foobar" / Segment / IntNumber / LongNumber)(foobar)

如果您无法转换foobar以返回路线,您还可以创建一个帮助器来转换函数,如下所示:

def foobar(str: String, i: Int, l: Long): String = s"$str : $i : $l"

def fromStringFunc3[T1, T2, T3](f: (T1, T2, T3) ⇒ String): (T1, T2, T3) ⇒ Route =
(t1, t2, t3) ⇒ complete(f(t1, t2, t3))

// usage
path("foobar" / Segment / IntNumber / LongNumber)(fromStringFunc3(foobar))

你必须为所有的arities重新创建这个函数(或者使用shapeless构建一些更灵活的东西,这是一种高级练习;)。