"Lifting" 将 Scala 函数转换为 HttpRequest 处理器

"Lifting" A Scala Function into an HttpRequest Processor

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

举个例子,给定一些函数

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

"lifting" 函数处理 Path 会很有用。例如 URL 路径可以是

/foobar/einstein/42/2016

提升函数看起来像:

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 部分转换为匹配类型。示例 URL 将通过调用 foobar("enstein", 42, 2016).

的结果完成

图书馆有没有办法做到这一点?如果不是,有没有办法定义升降机?

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

您似乎想要创建 Route 而不是 Directive。不同之处在于 Route 实际上处理请求,而 Directive 包装具有更多功能的路由。你似乎想要最终处理一个请求,所以它应该是一个 Route.

您似乎在寻找适用于所有功能的非常通用的解决方案。目前很难(甚至不可能)做到这一点,尤其是因为您需要以某种方式指定应如何解析参数。 spray-routing / akka-http 路由实际上在某种程度上不鼓励这种风格,而是支持更明确的做事方式。

例如给定 (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 转换为 return 路由,您还可以创建一个帮助函数来转换函数,如下所示:

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))

不过,您必须为所有参数重新创建此函数(或者使用 shapeless 构建更灵活的东西,这是一项高级练习;))。