Google App Engine - 如何正确gzip请求

时间:2017-08-11 07:30:51

标签: http google-app-engine http-post gzip

在我的Google App Engine应用程序(标准环境,用Java + Scala编写)中,我希望对服务器的一些请求进行gzip压缩。经过一些实验后,我得到了大部分工作,但有几点我不确定。我没有找到关于正确的客户端gzip使用的文档,大多数文档和示例似乎都关心服务器编码其响应,因此我不确定我是否正在做我应该做的一切。

我以这种方式发送请求(在客户端应用程序中使用akka.http):

        val uploadReq = Http().singleRequest(
          HttpRequest(
            uri = "https://xxx.appspot.com/upload-a-file",
            method = HttpMethods.POST,
            headers = List(headers.`Content-Encoding`(HttpEncodings.gzip)) 
            entity = HttpEntity(ContentTypes.`text/plain(UTF-8)`,  Gzip.encode(ByteString(bytes)))
          )
        )

在生产GAE服务器上,我得到了已经解码的gzip压缩请求体,编码头仍然存在。在开发服务器上,这是不同的,标题也存在,但请求正文仍然是gzip压缩。

解码请求输入流的代码不是问题,但是如果我应该解码请求体,我没有找到一种干净的方法来检查我的服务器代码。我目前的解决方法是,如果客户端知道它正在与开发服务器通信,它根本不使用gzip编码,我从不尝试解码请求体,因为我依靠Google App Engine为我这样做。

  • 我应该在客户端上对请求主体进行不同的编码吗?
  • 是否有其他方法可以在服务器上识别传入请求主体是否需要解码?
  • 我可以假设Google App Engine生产服务器会为我解码身体吗?

1 个答案:

答案 0 :(得分:0)

对于记录:我最终得到的解决方案是我检查请求正文,如果它看起来像gzip,我解压缩它,完全忽略标题。这适用于prod(App Engine进行解压缩,代码无损)和dev(代码解压缩)。 Scala代码如下:

def decompressStream(input: InputStream): InputStream = {
  val pushbackInputStream = new PushbackInputStream(input, 2)
  val signature = new Array[Byte](2)
  pushbackInputStream.read(signature)
  pushbackInputStream.unread(signature)
  if (signature(0) == 0x1f.toByte && signature(1) == 0x8b.toByte) {
    new GZIPInputStream(pushbackInputStream)
  } else pushbackInputStream
}

理论上的缺点是有人可能偶然发送包含0x1f / 0x8b标头的请求。在我的情况下这不可能发生,因此我很好。