喷涂路由:如何响应不同的内容类型?

时间:2014-01-14 16:22:54

标签: scala routing http-headers spray http-accept-header

在喷涂中,我想根据给定的Accept标题回复不同的内容类型。我在question by rompetroll中看到了一些建议,但我想知道是否有任何规范的方法(即简单或已经实施)。

本质上我想象的应该是:

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

提前致谢。

2 个答案:

答案 0 :(得分:15)

参见测试in this commit

我把它复制在这里作为参考:

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))
}

答案 1 :(得分:8)

Spray实际上正在调查Accept标头值并对其进行验证。因此,如果路线返回application/jsontext/plain而客户接受image/jpeg,则会返回406 Not Acceptable。如果客户从此路线请求application/jsontext/plain,则他将收到匹配内容类型的回复。

这里的主要技巧是使用正确的marshallers作为返回对象。 您可以阅读有关编组here的更多信息。

此外,您可以使用respondWithMediaType指令覆盖MediaType,但我认为最好使用正确的marshallers。