8

在喷雾中,我想根据给定的Accept标题以不同的内容类型进行响应。我在rompetroll 的问题中看到了一些建议,但我想知道是否有任何规范的方法(即简单或已经实现)。

本质上,我想应该发生的事情是这样的:

path("somepath") {
  get {
    // Find whatever we would like to return (lazily)
    ...
    // Marshall resource and complete depending on the `Accept` header
    ...
  }
}

提前致谢。

4

2 回答 2

15

请参阅此提交中的测试。

我在这里复制它以供参考:

case class Data(name: String, age: Int)
object Data {
  import spray.json.DefaultJsonProtocol._
  import spray.httpx.SprayJsonSupport._

  // don't make those `implicit` or you will "ambiguous implicit" errors when compiling
  val jsonMarshaller: Marshaller[Data] = jsonFormat2(Data.apply)
  val xmlMarshaller: Marshaller[Data] =
    Marshaller.delegate[Data, xml.NodeSeq](MediaTypes.`text/xml`) { (data: Data) ⇒
      <data><name>{ data.name }</name><age>{ data.age }</age></data>
    }

  implicit val dataMarshaller: ToResponseMarshaller[Data] =
    ToResponseMarshaller.oneOf(MediaTypes.`application/json`, MediaTypes.`text/xml`)  (jsonMarshaller, xmlMarshaller)
}

然后,您在路由中使用complete应该就足够了,内容类型协商会自动处理:

get {
  complete(Data("Ida", 83))
}
于 2014-01-15T09:20:02.270 回答
8

Spray 实际上正在查看Accept标头值并对其进行验证。因此,如果 route 正在返回application/jsontext/plain并且客户端接受image/jpeg,则 spray 将返回406 Not Acceptable。如果客户端将请求application/jsontext/plain来自此路由,那么他将收到具有匹配 Content-Type 的响应。

这里的主要技巧是使用正确的编组器返回对象。您可以在此处阅读有关编组的更多信息。

您也可以使用respondWithMediaType指令覆盖MediaType,但我认为最好使用正确的编组器。

于 2014-01-14T17:48:01.307 回答