Search code examples
scalafinagle

How I can make a request with params from finagle client?


I’m getting started with a Finagle server (twitter/finagle):

import com.twitter.finagle.{Http, Service}
import com.twitter.util.{Await, Future}
import java.net.InetSocketAddress
import org.jboss.netty.handler.codec.http._

object Server extends App {
  val service = new Service[HttpRequest, HttpResponse] {
    def apply(req: HttpRequest): Future[HttpResponse] =
      Future.value(new DefaultHttpResponse(
        req.getProtocolVersion, HttpResponseStatus.OK))
  }
  val server = Http.serve(":8080", service)
  Await.ready(server)
}

Client (twitter/finagle):

import com.twitter.finagle.{Http, Service}
import com.twitter.util.{Await, Future}
import java.net.InetSocketAddress
import org.jboss.netty.handler.codec.http._

object Client extends App {
  val client: Service[HttpRequest, HttpResponse] =
    Http.newService("localhost:8080")
  val request =  new DefaultHttpRequest(
    HttpVersion.HTTP_1_1, HttpMethod.GET, "/")
  val response: Future[HttpResponse] = client(request)
  response onSuccess { resp: HttpResponse =>
    println("GET success: " + resp)
  }
  Await.ready(response)
}

How do I send data like Map("data_id" -> 5) from the client to the server? And where in the server do I receive it? Do I have to add a callback to the server?

I haven’t found it by searching. If you can give me a link with an example, that will be enough.


Solution

  • Finagle is a very thin library. That means that you'll have to handle most of the "magic" by yourself.

    To make the request with parameters from the Client, I use these helper methods:

      def buildUri(base: String, path: String, params: Map[String, String] = Map.empty): String = {
        val p = if (params.isEmpty) ""
        else params map { case (k,v) => urlEncode(k) + "=" + urlEncode(v) } mkString ("?", "&", "")
        base + path + p
      }
    
      def urlEncode(url: String): String = URLEncoder.encode(url, "UTF-8")
    

    And then I call it like this:

    val url = buildUri(baseAddress, path, defaultParams ++ params)
    val req = RequestBuilder().url(url).setHeader("Accept", "*/*").buildGet
    client(req)
    

    As for the server you have to do basically the same thing and parse the parameters by hand. Either using java.net.URI or even org.jboss.netty.handler.codec.http.QueryStringDecoder.

    Of course you can also use URI and QueryStringEncoder to encode as well, instead of using my helper methods.

    That said, if you want to do that on higher level, you can use one of these libraries above Finagle: