Ramon J Romero y Vigil Ramon J Romero y Vigil - 1 year ago 67
reST (reStructuredText) Question

"Lifting" A Scala Function into an HttpRequest Processor

I'm looking for some way of converting a function which takes basic parameter types and using it to process an akka

. I want the
to be automatically processed and passed to the function.

As an example, given some function

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

It would be useful to have a way of "lifting" the function to process a
. An example URL Path could be


The lifting function would look something like:

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


Which could then be used in the following way:

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

This lifting function would have to loop through the function parameter types and convert the corresponding Path section to the matching type before the values are passed into the function. The example URL would be completed with the result of the call
foobar("enstein", 42, 2016)

Is there anyway to do this in the libraries? If not, is there a way to define lifter?

Thank you in advance for your consideration and response.

Answer Source

You seem to want to create a Route rather than a Directive. The difference is that a Route actually handles a request while a Directive wraps a route with more functionality. You seem to want to finally handle a request, so it should be a Route.

You seem to look for a very generic solution that would work for every function. This is currently only very hard (or even impossible) to do not least because you somehow need to specify how parameters should be parsed. spray-routing / akka-http routes actually somewhat discourage such a style in favor of a more explicit way of doing things.

E.g. given your given function definition of (String, Int, Long) => Route, the route would look like this:

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

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

If you cannot convert foobar to return a route you can also create a helper that converts the function like this:

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

You will have to recreate this function for all arities, though (or build something more flexible with shapeless which is an advanced exercise ;) ).

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download