从 Akka-HTTP 路由中提取查询参数的警告消息

Warning message extracting query parameters from an Akka-HTTP route

我是第一次使用 Akka-HTTP,在构建处理带有多个参数的 GET 请求的路由时遇到了一些问题。这是我的路线的简化版本——它接受 2 个查询参数,然后将它们包装在 class 和 return 中 JSON 格式(使用 Circe):

def echo(latitude: Double, longitude: Double) = Future.successful { Coordinates(latitude, longitude) }

    val route = get {
      pathPrefix("foo") {
        path("echo") {
          parameters('latitude.as[Double], 'longitude.as[Double]) { 
            (latitude, longitude) =>
              complete(echo(latitude, longitude))
        }
      }
    }
  }

虽然这按预期工作,但我在编译期间收到以下警告:

"No automatic adaptation here: use explicit parentheses. [warn]
signature: ParameterDirectives.parameters(pdm: akka.http.scaladsl.server.directives.ParameterDirectives.ParamMagnet): pdm.Out [warn] given arguments: scala.Symbol("latitude").as[Double], scala.Symbol("longitude").as[Double] [warn] after adaptation: ParameterDirectives.parameters((scala.Symbol("latitude").as[Double], scala.Symbol("longitude").as[Double]): akka.http.scaladsl.server.directives.ParameterDirectives.ParamMagnet{type Out = akka.http.scaladsl.server.Directive[(Double, Double)]}) [warn]
parameters('latitude.as[Double], 'longitude.as[Double]) { (latitude, longitude) =>"

按照不同的示例,我尝试了以下路线,但尽管它在没有任何警告的情况下编译,但它总是 returns a 404:

  val route = get {
    pathPrefix("foo") {
      path("echo" / DoubleNumber / DoubleNumber) { 
        (latitude, longitude) =>
          complete(echo(latitude, longitude))
    }
  }
}

如果有人知道如何修复第一条路线的警告或让第二条路线起作用,我将非常感谢您的帮助。此外,我正在处理的实际服务将有 4 个 GET 方法——不同的路径和 return 类型,但它们都有相同的 4 个参数。有没有一种方法可以在编写路线时将其结构化以最小化样板文件?同样,我对 Akka-HTTP 还是很陌生,所以任何建议或意见将不胜感激!

谢谢, 蒂姆

1) 编译器将您的参数与自动元组包装在一起,在这种情况下您可能会有一个编译器标志抛出警告(scala -Ywarn-adapted-args?)。解决方法是使元组显式化,例如

parameters(('latitude.as[Double], 'longitude.as[Double])) {...}

2) 这个看起来不错。下面的示例主要

object Main extends App {
  val route = get {
    pathPrefix("foo") {
      path("echo" / DoubleNumber / DoubleNumber) {
        (latitude, longitude) =>
          complete(latitude + ":" + longitude)
      }
    }
  }

  implicit val sys = ActorSystem()
  implicit val mat = ActorMaterializer()

  Http().bindAndHandle(route, "0.0.0.0", 9080)
}

适用于以下请求

http://localhost:9080/foo/echo/2.356/25.6346

3) 对于将逻辑位提取到可重用函数的问题,这就是 Directives 的目的。假设你想提取匹配 lat 和 lng 参数的位,你可以这样做:

  def extractLatLng(prefix: String): Directive[(Double, Double)] = path(prefix / DoubleNumber / DoubleNumber)

  val route = get {
    pathPrefix("foo") {
      extractLatLng("echo") { (lat, lng) ⇒
        complete(lat + ":" + lng)
      }
    }
  }