【问题标题】:Rest clients do not unzip automatically gzipped responses休息客户端不会自动解压缩 gzip 响应
【发布时间】:2017-01-12 06:47:38
【问题描述】:

我压缩了我的 JSON 标头,如下所示:

ByteArrayOutputStream out = new ByteArrayOutputStream();
GZIPOutputStream gzip = new GZIPOutputStream( out );
gzip.write( responseBody.encodePrettily().getBytes( "UTF-8" ) );
gzip.close();
byte[] bytes = out.toByteArray();
String response = Base64.getEncoder().encodeToString( bytes );

我从服务器发送此响应。 在任何浏览器上,响应都会自动解压缩并检索 json 数据。但是在 Postman、Insomnia 或 RestClient (Mozilla Addon) 上发送 GET 请求时,我得到的是编码的 gzip 而不是 json 数据:

H4sIAAAAAAAAAM2POwvCMBSF90L/wyVzB9tmcnZxcLFuIiE0VwikD/IQpOS/20RL1cGt0vWcw/3uN6QJANFonLIE...

我怎样才能把它解压缩?我尝试了几个 Rest Client,但没有一个像浏览器那样解压缩。

我无处可寻,我开始感到绝望。

【问题讨论】:

    标签: json rest http gzip


    【解决方案1】:

    您需要包含一个 Content-Coding 响应头字段,指示“gzip”(请参阅​​https://greenbytes.de/tech/webdav/rfc7231.html#data.encoding

    【讨论】:

    • 我做到了,但没有帮助。我什至在标题中添加了一个传输编码。我总是得到:content-coding: gzip content-type: application/json; charset=utf-8 transfer-coding: gzip content-encoding: gzip transfer-encoding: chunked 和我上面写的响应正文。
    • 因为我需要在测试中解压缩它们。因此,它们需要进行 Base64 编码才能检索有效的字符串而不是二进制文件,例如 �]�� �0E�B��������Cu �yB MC�"���yZ���˽K���1Yp�;,��l ...
    • 好吧,它们不应该是 base64 编码的。 HTTP 响应主体可以很好地携带二进制文件。标准客户放弃这一点也就不足为奇了。
    • 即使我不对它进行 base64 编码,我仍然得到相同的结果:��������]�� �0E�B��������Cu �yB MC�"����yZ���˽K����1Yp�;,��l��){%E)��%kw_A��x�=�uɄ����PI+�� .. .即使内容编码标头设置为gzip。似乎没有解决方案。所以我在邮递员中添加了一个请求标头Accept-Encoding : json,并在压缩之前在我的代码中验证。如果设置了标头,我不压缩。它并不完美,但比以前更好。
    • 没有内容编码“json”。您的意思是 Content-Type 吗??? FWIW,给定的 HTTP 客户端库是否自动解包内容编码通常是一个配置问题 - 调用者可能必须自己做。
    【解决方案2】:

    问题解决了!实际上,没有必要像我在问题中显示的那样手动压缩响应,因为我们使用的是 Vert.X。

    Vert.X 提供了一个巧妙的选项,可以在 HttpServerOptions 中设置,以便在可能的情况下自动进行压缩(即客户端支持压缩)。 Postman 和任何其他 REST 客户端(即浏览器或其他)获取压缩响应并自动解压缩!

    我浪费了很多时间,但至少学到了一些有用的东西。这就是我想与你分享的原因。

    如果您使用 Vert.X,这行代码将为您完成工作:

    HttpServerOptions options = new HttpServerOptions().setCompressionSupported( true );

    然后在创建 HttpServer 时简单地使用这个 HttpServerOptions 实例:

    HttpServer server = vertx.createHttpServer( options );

    PS:您可以在检查客户端返回的响应标头时验证压缩是否确实发生。你会找到content-encoding : gzip

    【讨论】: