內容協商
內容協商指對同一URI的不同返回形式。比如說一個同時支持XML、JSON等返回格式的Web Service。服務端驅動的內容協商本質上用Accept* 請求頭實現。HTTP 規範中的內容協商請見這裏。
語言
可以用 play.api.mvc.RequestHeader#acceptLanguages 方法從 Accept-Language 頭中獲取支持的語言,並使用 quality 值排序。play.api.mvc.Controller#lang 方法向 action 提供一個implicit play.api.i18n.Lang,以供 Play選擇最佳的適配語言(如果你的應用不支持適配的語言,將使用應用的默認語言)。
內容
類似的,play.api.mvc.RequestHeader#acceptedTypes 方法指明瞭請求可接受result的MIME類型。它會從請求中Accept頭,並按照quality排序。
事實上 Accept 頭包含的是媒體範圍,而不是具體的MIME類型(e.g. 設置 text/* range可以支持所有text result請求,而 */* 將代表支持任意result類型)。Controllers 提供了一個高級的 render 方法來處理媒體範圍。如下例所示:
val list = Action { implicit request =>
val items = Item.findAll
render {
case Accepts.Html() => Ok(view.html.list(items))
case Accepts.Json() => Ok(Json.toJson(items))
}
}
Accepts.Html() 和 Accepts.Json() 將嘗試分別匹配指定的 text/html 和 application/json 媒體範圍。render 方法接受一個 play.api.http.MediaRande => play.api.mvc.Result 偏函數,並嘗試使用從Accept頭中的媒體類型來進行模式匹配。如果沒匹配到任意類型,將返回 NotAcceptable。
舉個例子,一個客戶端的Accept頭如下: */*; q=0.5, application/json,表示接受任意的頭但是 application/json 優先,因此上面的代碼段將返回JSON。如果是 application/xml 格式的 Accept Header表示只接受XML,上邊的例子將返回 NotAcceptable。
提取Request
render方法包含的開箱即用MIME類型清單可以參見 play.api.mvc.AcceptExtractors.Accepts對象。你也可以方便的利用 play.api.mvc.Accepting 來創建自己的extractor。下面的例子可用來檢查請求頭是否包含 audio/mp3 MIME類型:
val AcceptsMp3 = Accepting("audio/mp3")
render {
case AcceptsMp() => ???
}