Как приложение Play 2 может отвечать на разные заголовки "Принять" от клиента?

В 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(...)
  }
}

Есть ли идиома Play для этого, или я просто извлекаю значение заголовка Accept из запроса?

Ответы

Ответ 1

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

Ответ 2

Я только что выпустил 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