0

I'm having trouble reading this line of scala in a legacy system I have inherited.

post("tokens" :: Auth() :: stringBody) { (_: String, token: String) =>

If it's required, I can post the lines before and after, but I assumed the line itself would have some meaning to a Scala developer.

The post method comes from the finch library, here is the method signature and comment:

/**
   * A combinator that wraps the given [[Endpoint]] with additional check of the HTTP method. The
   * resulting [[Endpoint]] succeeds on the request only if its method is `POST` and the underlying
   * endpoint succeeds on it.
   */
  def post[A](e: Endpoint[A]): EndpointMapper[A] = new EndpointMapper[A](Method.Post, e)

I assume the underscore is a match all for a string, but what is this matching? I assume it was matching the arguments in the post method, but there are three parameters and two things captured.

I assume the method matches to the "tokens" REST endpoint value, then expects an Auth header and captures the string body. I'm confused what the double colon argument means in this case, as it would be behaving different the first and second time it is used.

dahui
  • 2,128
  • 2
  • 21
  • 40
  • What is the signature of the post method? In this case, the underscore signifies an ignored parameter to a function. The `{ (_: Int, token: String) => ` part is the beginning of a lambda function taking two strings as input. – marstran Oct 16 '18 at 16:07
  • I will update the question with the signature and comment of the method – dahui Oct 16 '18 at 16:10
  • Updated, thanks for the comment – dahui Oct 16 '18 at 16:14

1 Answers1

1

As you posted the link to finch, it is a combinator API for finagle http service.

  • You compose a finch endpoint as combination of path, param, header, cookie, body etc. see codebase here
  • you combine the endpoint using :: operator

Endpoint#:: has a definition as below:

final def ::[B](other: Endpoint[B])(implicit pa: PairAdjoin[B, A]): Endpoint[pa.Out]

So, in your example you must be composing endpoint with path, probably header and request body. While {} block being your on success of the endpoint. Since you are composing header and body, think of it outputting two results. In scala if you are not going to use a variable, you can discard naming it with _.

Example, List(1, 2).map(elem => elem * 2) is equivalent to List(1, 2).map(_ * 2)

Example of an finch endpoint,

  val auth = post("tokens" :: header[String]("auth") :: stringBody) {
    (authHeader: String, body: String) =>
      Ok(s"""
         {
            "auth": "$authHeader",
            "body": "$body"
         }
       """.stripMargin)
  }

  def main(args: Array[String]): Unit = {

    val endpoints: Service[Request, Response] = auth.toService

    Await.ready(Http.server.serve(":9090", endpoints))

  }

once you run it you can consume the endpoint using

$ curl --request POST -H "auth: some header" -d "some data" localhost:9090/tokens
"\n         {\n            \"auth\": \"some header\",\n            \"body\": \"some data\"\n         }\n       "
prayagupa
  • 30,204
  • 14
  • 155
  • 192