How to bind request body in Finch

Here is the code to bind the request parameter to the router.

val testReader: Endpoint[Test] = Endpoint.derive[Test].fromParams val test: Endpoint[String] = post("test" ? testReader) { t : Test => { Created("OK") }} 

I am using fromParams method. This method can very easily bind query parameters. However, I do not know what a similar way I can bind the request body in finch

Thank you very much in advance

+7
scala web-services finagle finch
source share
1 answer

To provide a complete working example, I will take the case class as follows:

 case class Test(foo: Int, bar: String) 

And some queries like this:

 import com.twitter.finagle.http.{ Method, Request, RequestBuilder } import com.twitter.io.{ Buf, Reader } val queryParamPost = Request(Method.Post, "/test?foo=1&bar=whatever") val testJsonBuf = Buf.Utf8("""{ "foo": 1, "bar": "whatever" }""") val bodyPost = RequestBuilder().url("http://localhost:8080/test").buildPost(testJsonBuf) 

Now that you are writing the following ...

 import io.finch._ val testParams: Endpoint[Test] = Endpoint.derive[Test].fromParams val test: Endpoint[Test] = post("test" ? testParams) { test: Test => Created(test) } 

What happens is that Finch uses the generic output (powered by Shapeless) to determine (at compile time) how to parse the query parameters as Test . Then you can check the endpoint as follows:

 import io.finch.circe._ import io.circe.generic.auto._ test.toService.apply(queryParamPost).onSuccess { response => println(s"$response: ${ response.contentString }") } 

What will print:

 Response("HTTP/1.1 Status(201)"): {"foo":1,"bar":"whatever"} 

Here I use Circe generic output to automatically encode the "created" Test as JSON for the response.

You can also use Circe to get a reader for the request body:

 val testBody: Endpoint[Test] = body.as[Test] val test2: Endpoint[Test] = post("test" :: testBody) { test: Test => Created(test) } 

This is almost the same as Test above, but we use body to get an Endpoint[String] that will read the request body, and then as to indicate that we want the content to be parsed as JSON and decoded as a Test value. We can test this new version as follows:

 test2.toService.apply(bodyPost).onSuccess { response => println(s"$response: ${ response.contentString }") } 

And again we get the answer that we expect.

In general, if you want to read certain information about an incoming request, you will use one of the basic Endpoint provided by Finch (see docs for a more complete list), and then use as , map , etc. on Endpoint to turn it into the form you need.

+9
source share

All Articles