博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
PlayScala 2.5.x - 关于Content-Type的注意事项
阅读量:6271 次
发布时间:2019-06-22

本文共 2222 字,大约阅读时间需要 7 分钟。

hot3.png

在Play项目中我们经常需要开发一些自定义Filter完成一些特定任务,在Filter实现中通常需要根据Response的Content-Type做相应的处理。例如实现一个CacheFilter只缓存js/css/img等静态文件,LoggerFilter只打印html响应的请求,GzipFilter忽略image类型响应(因为image本身就是压缩类型)。所以正确的获取Content-Type在开发Filter时显得尤为重要。在Play2.5.x中,Content-Type的获取方式发生了一些变化,下面对比Play2.4.x做一些简单的说明。

从Play2.5.x开始,Play将逐渐地从Iteratee迁移到Akka Stream,在官方文档“Play 2.5 Migration Guide”第1段中就说明了这一点:

  •  – Migrating to Akka Streams, now used in place of iteratees in many Play APIs

对于我们的日常开发来说,最大的影响就是Result的类型声明发生了变化,在Play2.4.x中Result的类型声明为:

case class Result(header: ResponseHeader, body: Enumerator[Array[Byte]],    connection: HttpConnection.Connection = HttpConnection.KeepAlive)

而在Play2.5.x中,body的类型从Enumerator变成了HttpEntity:

case class Result(header: ResponseHeader, body: HttpEntity)

下面我们通过生成一个简单的json响应对比一下2.4.x和2.5.x之间的实现差异,生成json代码如下:

Ok(Json.obj("success" -> true))

因为传入的是JsValue类型,所以Play会自动添加如下响应头:

Content-Type:application/json

Play2.4.x的相应实现在Results.Status.apply方法中,代码如下:

class Status(status: Int) extends Result(header = ResponseHeader(status), body = Enumerator.empty, connection = HttpConnection.KeepAlive) {    def apply[C](content: C)(implicit writeable: Writeable[C]): Result = {    Result(      ResponseHeader(status, writeable.contentType.map(ct => Map(CONTENT_TYPE -> ct)).getOrElse(Map.empty)),      Enumerator(writeable.transform(content))    )  }...

注意apply方法的第2行,Play2.4.x根据响应内容将Content-Type设置到ResponseHeader中。

再来看Play2.5.x,实现也在Results.Status.apply方法中,代码如下:

class Status(status: Int) extends Result(header = ResponseHeader(status), body = HttpEntity.NoEntity) {  def apply[C](content: C)(implicit writeable: Writeable[C]): Result = {    Result(      header,      writeable.toEntity(content)    )  }...

注意apply方法的第2行,Play2.5.x并没有在ResponseHeader设置请求头。继续追踪HttpEntity的实现,发现它有一个contentType方法声明,其值来自隐式的ContentTypeOf[JsValue]参数:

/**   * The content type of the entity, if known.   */  def contentType: Option[String]

好吧,真相浮出水面了:Play2.5.x默认将Content-Type响应头设置在HttpEntity上,而不是像Play2.4.x那样设置在响应头上。

所以Play2.5.x中正确获取Content-Type的方法是使用response.body.contentType,下面是配置GzipFilter的代码示例:

new GzipFilter(shouldGzip = (request, response) =>  response.body.contentType.exists(_.startsWith("text/html")))

 

参考:

 

转载于:https://my.oschina.net/joymufeng/blog/684715

你可能感兴趣的文章
《UNIX网络编程 卷1:套接字联网API(第3版)》——8.6 UDP回射客户程序:dg_cli函数...
查看>>
不要将时间浪费到编写完美代码上
查看>>
《第一桶金怎么赚——淘宝开店创业致富一册通》一一第1章 创业梦想,怎样起步...
查看>>
基于容器服务的持续集成与云端交付(三)- 从零搭建持续交付系统
查看>>
《算法基础:打开算法之门》一3.4 归并排序
查看>>
高德开放平台开放源代码 鼓励开发者创新
查看>>
《高并发Oracle数据库系统的架构与设计》一2.5 索引维护
查看>>
《Exchange Server 2010 SP1/SP2管理实践》——2.4 部署外部网络环境
查看>>
Firefox 是 Pwn2own 2014 上攻陷次数最多的浏览器
查看>>
阿里感悟(十八)- 应届生Review
查看>>
《计算广告:互联网商业变现的市场与技术》一第一部分 在线广告市场与背景...
查看>>
话说模式匹配(5) for表达式中的模式匹配
查看>>
《锋利的SQL(第2版)》——1.7 常用函数
查看>>
《Arduino家居安全系统构建实战》——1.5 介绍用于机器学习的F
查看>>
jquery中hover()的用法。简单粗暴
查看>>
线程管理(六)等待线程的终结
查看>>
spring boot集成mongodb最简单版
查看>>
DELL EqualLogic PS存储数据恢复全过程整理
查看>>
《Node.js入门经典》一2.3 安装模块
查看>>
《Java 开发从入门到精通》—— 2.5 技术解惑
查看>>