Play WS - 检查压缩头
Posted
技术标签:
【中文标题】Play WS - 检查压缩头【英文标题】:Play WS - check compression headers 【发布时间】:2016-09-08 12:17:36 【问题描述】:我通过关注those instructions 为我的网络服务 (Play 2.4) 中的所有响应启用了 gzip 压缩。易于设置,我可以看到它就像一个魅力,用 curl 和 wireshark 检查发送的响应是压缩的。
现在我想成为一名优秀的开发人员并添加一个集成测试以确保下周没有人破坏 HTTP 压缩。乐趣从这里开始!我的测试如下所示:
"use HTTP compression" in
forAll(endPoints) endPoint =>
val response = await(
WS.url(Localhost + port + "/api" + endPoint).withHeaders("Accept-Encoding" -> "gzip").get()
)
response.header("Content-Encoding") mustBe Some("gzip")
但是,测试失败,因为 WS 的响应标头不包含内容编码信息,并且正文以纯文本形式返回,未压缩。
[info] - should use HTTP compression *** FAILED ***
[info] forAll failed, because:
[info] at index 0, None was not equal to Some("gzip") (ApplicationSpec.scala:566)
在运行此测试时检查wireshark 中的流量我可以清楚地看到服务器正在返回一个gzip 编码的响应,所以看起来WS 以某种方式透明地解压响应并剥离内容编码标头?有没有办法获得带有完整标头的纯压缩响应,以便检查响应是否被压缩?
【问题讨论】:
您找到解决方案了吗? 查看我的答案below(它最终有点太大,无法回复评论)。我最终使用普通的旧 Java 类并完全绕过 Play-WS 进行这个单一测试,因为我需要更底层的东西。 【参考方案1】:我认为你做不到。如果我没记错的话,这里的问题是 Netty 返回的内容已经解压,所以头部也被删除了。
在 AsyncHTTPClient 中有一个配置可以设置 (setKeepEncoding),但不幸的是,这仅适用于 2.0 及更高版本,并且 Play 2.4 WS lib 使用版本 1.9.x。
不管怎样,Play给你的客户端已经配置好了,不知道你能不能调整一下。但是您可以创建一个新客户端来模拟该行为:
// Converted from Java code: I have never worked with those APi's in Scala
val cfg = new AsyncHttpClientConfig.Builder().addResponseFilter(new ResponseFilter
override def filter[T](ctx: FilterContext[T]): FilterContext[T] =
val headers = ctx.getRequest.getHeaders
if (headers.containsKey("Accept-Encoding"))
ctx.getResponseHeaders.getHeaders.put("Content-Encoding", List("gzip"))
ctx
).build()
val client: NingWSClient = NingWSClient(cfg)
client.url("...") // (...)
同样,这只是模拟您需要的结果。此外,建议使用比将gzip
添加为Content-Encoding
更聪明的逻辑(例如:将请求的第一个算法放入“接受编码”中)。
【讨论】:
标头名为Accept-Encoding
【参考方案2】:
事实证明,我们不能真正将 Play-WS 用于这个特定的测试,因为它已经返回了未压缩的内容并去除了标题(请参阅 @Salem 的有见地的答案),因此无法检查响应是否被压缩。
但是,使用标准 Java 类编写一个检查 HTTP 压缩的测试很容易。我们只关心在发送带有Accept-Encoding: gzip
的请求时服务器是否以(有效的)GZIP 形式回答。这是我最终得到的结果:
forAll(endPoints) endPoint =>
val url = new URL(Localhost + port + "/api/" + endPoint)
val connection = url.openConnection().asInstanceOf[HttpURLConnection]
connection.setRequestProperty("Accept-Encoding", "gzip")
Try
new GZIPInputStream(connection.getInputStream)
must be a 'success
【讨论】:
以上是关于Play WS - 检查压缩头的主要内容,如果未能解决你的问题,请参考以下文章