1
votes

I'm working with Akka-HTTP for the first time and am having some issues constructing a route to handle GET requests with multiple parameters. Here's a simplified version of my route-- it takes in 2 query parameters and then just wraps them in a case class and returns them in JSON format (using 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))
        }
      }
    }
  }

Although this works as expected, I'm getting the following warning during compilation:

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

Following a different example, I tried the following route, but although it compiles without any warnings, it always returns a 404:

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

If anyone knows how I can fix the warning with the first route or get the second route to work, I would really appreciate the help. Also, the real service I'm working on will have 4 GET methods-- different paths and return types, but they will all have the same 4 parameters. Is there a way to structure this to minimize boilerplate when writing the routes? Again, I'm very new to Akka-HTTP, so any suggestions or advice would be very much appreciated!

Thanks, Tim

1

1 Answers

3
votes

1) the compiler is wrapping your parameters together with auto-tupling, and you're likely to have a compiler flag that throws warnings in this case (scala -Ywarn-adapted-args ?). The fix would be to make the tupling explicit, e.g.

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

2) This one looks just fine. The sample main below

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

works fine with the following request

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

3) For what concerns extracting bits of logic to reusable functions, that's what Directives are for. Say you want to extract the bit that matches lat and lng params, you could do something like:

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

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