如何在Finch中绑定请求体

时间:2016-05-01 12:48:32

标签: web-services scala finagle finch

以下是将请求参数绑定到路由器的代码。

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

我正在使用方法fromParams。此方法可以非常酷的方式绑定请求参数。但是,我不知道哪种类似的方法可以在雀体中绑定请求正文

非常感谢提前

1 个答案:

答案 0 :(得分:9)

为了提供一个完整的工作示例,我将假设一个这样的案例类:

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

有些请求是这样的:

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)

现在写下面的内容......

import io.finch._

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

正在发生的事情是,Finch使用泛型派生(由Shapeless提供)来确定(在编译时)如何将查询参数解析为Test。然后,您可以像这样测试端点:

import io.finch.circe._
import io.circe.generic.auto._

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

将打印:

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

这里我使用Circe的泛型推导来自动将“创建的”Test编码为响应的JSON。

您还可以使用Circe为请求正文派生一个阅读器:

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

这与上面的test几乎完全相同,但我们使用body来获取将会读取请求正文的Endpoint[String],然后as来指定我们希望将内容解析为JSON并解码为Test值。我们可以像这样测试这个新版本:

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

我们会得到我们期待的答案。

通常,当您想要阅读传入请求的某种信息时,您将使用Finch提供的基本Endpoint之一(有关更完整的列表,请参阅the docs) ,然后在as上使用mapEndpoint等方法将其转换为您需要的形状。

相关问题