spray-can如何解包unmarshalled FormData

时间:2014-03-11 10:11:43

标签: scala akka spray

我有这样的事情:

case HttpRequest(POST, Uri.Path("/userAction"), headers, entity: HttpEntity.NonEmpty, protocol) =>
  val x = entity.as[spray.http.FormData].merge.asInstanceOf[spray.http.FormData].fields
  sender ! HttpResponse(entity="Got it: " + x)

打开HttpEntity似乎有点不方便,有更优雅的方式吗?

此外:是否可以从具有多个delacred变量的输入中获取数据?有没有更好的方法来访问FormData,例如作为Json还是HashMap?

1 个答案:

答案 0 :(得分:3)

您是否真的有理由使用喷雾罐实施此操作?在路由中,它更容易和自然:

lazy val yourRoute: Route = {
  (post & path("userAction")) {
    entity(as[SomeType]) { data =>
      // do what you want
    }
  }
}

在这个版本中,它都适用于您的类型(SomeType)的正确解组。但是如果你想坚持使用喷雾罐,你可以使用spray-httpx unmarshaller。我没有IDE靠近我,但这可能是这样的(我的项目实际代码中有一些Scalaz技巧):

case request @ HttpRequest(...) =>
  fromTryCatch(request.entity |> unmarshal[SomeType]) // returns Throwable \/ SomeType, like scala's Either type

这里也是正确的unmarshaller,例如,如果你想让你的实体以Json格式(即喷JsObject),那么你需要发出一个带有json有效负载的请求,写entity(as[JsObject])并提供一个隐含的来自spray.json.SprayJsonSupport的unmarshaller。我认为对FormData使用这种方法有点开销,因为简单的Post有效负载你有formFields指令,你可以写:

lazy val yourRoute: Route = {
  (post & path("userAction")) {
    formFields(...) { fields => // just enumerate field names from your FormData
      // do what you want
    }
  }
}

对于Map方法,如果相同,只需将spray.json.DefaultJsonProtocol添加到范围中,即可为地图添加unmarshaller。

仍然使用喷涂路由DSL比处理低级别的代码要好得多。如果您仍想使用,请查看spray.httpx.unmarshalling包,它包含不同类型的解组,用于实体,请求和响应。