Here is the code to bind request param 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 the method fromParams
. This method can bind request parameters in a very cool way. However, I dont konw which similiar way I can bind request body in the finch
Many thanks in advance
For the sake of providing a complete working example I'll assume a case class like this:
case class Test(foo: Int, bar: String)
And some requests 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 when you write 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's happening is that Finch is using generic derivation (powered by Shapeless) to determine (at compile time) how to parse the query params as a Test
. You can then test the endpoint like this:
import io.finch.circe._
import io.circe.generic.auto._
test.toService.apply(queryParamPost).onSuccess { response =>
println(s"$response: ${ response.contentString }")
}
Which will print:
Response("HTTP/1.1 Status(201)"): {"foo":1,"bar":"whatever"}
Here I'm using Circe's generic derivation to automatically encode the "created" Test
as JSON for the response.
You can also use Circe to derive 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 exactly the same as test
above, but we're using body
to get an Endpoint[String]
that will read the request body and then as
to specify that we want the content parsed as JSON and decoded as a Test
value. We can test this new version like this:
test2.toService.apply(bodyPost).onSuccess { response =>
println(s"$response: ${ response.contentString }")
}
And we'll get the answer we expect again.
In general when you want to read a certain kind of information of an incoming request, you'll use one of the basic Endpoint
s provided by Finch (see the docs for a more complete list), and then use methods like as
, map
, etc. on the Endpoint
to turn it into the shape you need.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With