改变默认的 Content-Type
结果内容的类型能够由你所指定的响应体的 Scala 值自动推断出来.
例如:
1 |
val textResult = Ok("Hello World!") |
将会自动设置 Content-Type
头为 text/plain
, 而:
1 |
val xmlResult = Ok(<message>Hello World!</message>) |
会设置 Content-Type header 为 text/xml
.
小贴士: 这是由
play.api.http.ContentTypeOf
类型类完成的.
这相当有用, 但是有时候你想手工改变它. 只需要调用 Result 的 as(newContentType)
方法来创建一个新的,类似的,具有不同 Content-Type
头的 Result:
1 |
val htmlResult = Ok(<h1>Hello World!</h1>).as("text/html") |
或者更好点, 用:
1 |
val htmlResult = Ok(<h1>Hello World!</h1>).as(HTML) |
注: 使用
HTML
代替"text/html"
的好处是会为你自动处理字符集,这时实际的 Content-Type 头会被设置为text/html; charset=utf-8
. 过会儿我们就能看到.
操控 HTTP 头
你还能添加 (或修改) Result 的任何 HTTP 头:
1 2 3 4 |
Ok("Hello World!").withHeaders( CACHE_CONTROL -> "max-age=3600", ETAG -> "xx" ) |
注:如是对一个 Result 设置了同一个 Header Key 对应的值,后面的会覆盖前面所设置的值.
Unmi: 上面的 withHeaders() 方法的原型是 Results(.scala) 中的 def withHeaders(headers: (String, String)*): A 方法。正如你看到的,withHeaders() 接收的是多个 (String, String) 元组类型。为什么可写成 CACHE_CONTROL,因为它的类型是字符串,字符串的 -> 操作符的返回值就是一个 (String, String) 元组类型。更多的 Header Key 定义在 play.api.http.HeaderNames 对象中。
为了演示相同 Key 时 Header 的覆盖关系,可以试下列代码:
1 2 3 4 5 6 |
Ok("Hello World!").withHeaders( "author" -> "Unmi", "siteFlag" -> "HongKong" ).withHeaders( "siteFlag" -> "USA" ) |
查看一下它的 Header 信息:
unmi@localhost$ curl -i http://localhost:9000
HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
author: Unmi
siteFlag: USA
Content-Length: 12
看到 siteFlag 存在时后面覆盖前面的设置,Key 不同时只添加。
设置和废弃 Cookie
Cookie 就是一种特殊的 HTTP 头,但是我们提供了一系列帮助方法简化了操作.
你可以很轻易的添加 Cookie 到 HTTP 响应中,使用:
1 2 3 |
Ok("Hello world").withCookies( Cookie("theme", "blue") ) |
而且, 要废弃先前存储在 Web 浏览器中的 Cookie 可用:
1 |
Ok("Hello world").discardingCookies("theme") |
改变基于文本的 HTTP 响应的字符集
对于基于文本的 HTTP 响应,正确处理好字符集是很重要的. Play 处理它的方式是采用 utf-8
为默认字符集.
字符集一方面用于转换文本响应成相应的字节通过网络 Socket 传送, 也用于更改 Content-Type
头为适当的 ;charset=xxx
扩展.
字符集由 play.api.mvc.Codec
类型类自动处理. 仅需要引入一个隐式的 play.api.mvc.Codec
实例到当前作用域中,从而各种操作所用到的字符集:
1 2 3 4 5 6 7 8 9 |
object Application extends Controller { implicit val myCustomCharset = Codec.javaSupported("iso-8859-1") def index = Action { Ok(<h1>Hello World!</h1>).as(HTML) } } |
这里, 因为作用域中存在一个隐式 charset 值, 它会被应用到 Ok(...)
方法来转换 XML 消息成 ISO-8859-1
编码的字节,或者是用于生成值为 text/html; charset=iso-8859-1
的 Content-Type 头.
现在,假如你想知道 HTML
方法是怎么工作的, 看看它的定义: Unmi 注:因为参数用了 implicit 关键字,所以如果在作用域中能找到 implicit 修饰的 Codec 类型变量将被隐式采用。
1 2 3 |
def HTML(implicit codec: Codec) = { "text/html; charset=" + codec.charset } |
假如你需要以通用的方式来处理字符集,你可以在自己的 API 中做同样的事情.