我的Play 2应用程序如何响应来自客户端的不同“Accept”标题?

时间:2012-06-16 04:14:38

标签: scala playframework-2.0

在Rails中,我能够做类似以下的事情:

respond_to do |format|
  format.xml { ... }
  format.json { ... }
end

并根据客户端在Accept标头中提供的内容执行相应的块。

如何在Play 2.0(Scala)中执行相同的操作?

我希望做一些看起来像这样的事情:

try {
  Resources.delete(id)
  Ok("done")
} 
catch { 
  case e: ClientReportableException =>
    ?? match { 
      case "application/xml" => Ok(<error>{e.message}</error>)
      case "application/json" => Ok(...)
  }
}

是否有播放习惯用法,或者我只是从请求中获取Accept标头的值?

2 个答案:

答案 0 :(得分:14)

在Play 2.1中,您可以编写以下内容:

request match {
  case Accepts.Xml() => Ok(<error>{e.message}</error>)
  case Accepts.Json() => Ok(…)
}

case语句按编写顺序进行尝试,因此如果客户端将HTTP Accept标头设置为*/*,则第一个标头将匹配(在此示例中为case Accepts.Xml())。因此,您通常希望首先编写Accepts.Html()案例,因为浏览器会将Accept标题设置为*/*

(注意:对于Java中的类似问题,您可能也对this answer感兴趣)

答案 1 :(得分:1)

我刚刚发布了Play!用于内容协商的2.0模块,名为mimerender(http://github.com/martinblech/play-mimerender)。

这个想法是你必须定义从你的域类到不同表示的映射:

val m = mapping(
  "text/html" -> { s: String => views.html.index(s) },
  "application/xml" -> { s: String => <message>{s}</message> },
  "application/json" -> { s: String => toJson(Map("message" -> toJson(s))) },
  "text/plain" -> identity[String]_
)

完成一次后,您可以在所有控制器中重复使用该映射:

object Application extends Controller {
  def index = Action { implicit request =>
    m.status(200)("Hello, world!")
  }
}

请注意,这是一个非常早期的版本,仅在Play 2.0.4上进行了测试