使用 HttpClient、REST 和 gzip 读取 JSON

Posted

技术标签:

【中文标题】使用 HttpClient、REST 和 gzip 读取 JSON【英文标题】:Read JSON with HttpClient, REST and gzip 【发布时间】:2021-08-14 12:10:52 【问题描述】:

我正在尝试使用 HttpClient、POST 方法调用休息服务。 该服务使用 gzip 压缩返回一个 json。 由于某种原因,响应的 json 与日志中始终为空的字符串变量“输出”无关。 See image 在调试中我只能看到 json 的初始值。 entity.getContent() 的结果是 org.apache.http.conn.EofSensorInputStream@30f5a68a。 通过 SoapUI 进行的相同测试似乎没问题。

Java 代码

HttpPost httpPost = new HttpPost(endpoint);
httpPost.addHeader("Content-Type", "application/json");
httpPost.addHeader(HttpHeaders.ACCEPT_ENCODING, "gzip");
httpPost.addHeader(HttpHeaders.ACCEPT, "application/json");         
httpPost.setEntity(new StringEntity(jsonRequest));
        
        try (CloseableHttpClient httpClient = HttpClientBuilder.create().disableRedirectHandling().build();
                CloseableHttpResponse res = httpClient.execute(httpPost)) 

            HttpEntity entity = res.getEntity();
            LOG.debug(entity.getContent());
                
            if (entity != null) 

                String output = EntityUtils.toString(entity, "UTF-8");
                LOG.debug(output); // <------- empty LOG
            

         catch (Exception exc) 
            LOG.error(exc);
        

Maven

<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
        <version>4.5.13</version>
    </dependency>

SAOP 用户界面请求

POST https://host HTTP/1.1
Accept-Encoding: gzip,deflate
Content-Type: application/json
Content-Length: 2627
Host: host
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.1.1 (java 1.5)

SAOP 用户界面响应

HTTP/1.1 200 OK
Date: Wed, 26 May 2021 08:48:57 GMT
Server: Apache
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
Strict-Transport-Security: max-age=31536000; includeSubDomains
Cache-Control: no-store, no-cache
Pragma: no-cache
X-Backside-Transport: OK OK
Content-Type: application/json
X-Global-Transaction-ID: dc640eac60ae0b794b55bcaf
APIHttpStatus: 200
Content-Encoding: gzip
Keep-Alive: timeout=65
Connection: Keep-Alive
Transfer-Encoding: chunked

"ShipmentResponse":"Response":"ResponseStatus":"Code":"1", "Description":"Success", "Alert":["Code":"120900", "Description":"User Id ...

Soap UI Json view

【问题讨论】:

通知传输编码:分块 【参考方案1】:

使用来自entity.getContent()的字符串

    GZIPInputStream gis = new GZIPInputStream(new ByteArrayInputStream(entity.getContent()));
    BufferedReader bf = new BufferedReader(new InputStreamReader(gis, "UTF-8"));
    String outStr = "";
    String line;
    while ((line=bf.readLine())!=null) 
      outStr += line;
    
    System.out.println("Output String lenght : " + outStr.length());

编辑:

似乎有一个 gzip 压缩内容的实体包装器: https://javadoc.io/doc/org.apache.httpcomponents/httpclient/latest/org/apache/http/client/entity/GzipDecompressingEntity.html

(new GzipDecompressingEntity(entity)).getContent()

【讨论】:

使用 GZIPInputStream gis = new GZIPInputStream(entity.getContent());我得到:java.util.zip.ZipException:不是 GZIP 格式getContent 返回一个 InputStream 另外,使用此代码,我得到一个完整的 EMPTY 日志行: [code] Reader decoder = new InputStreamReader(entity.getContent(), "UTF-8"); BufferedReader buffered = new BufferedReader(decoder); final String line = buffered.readLine(); LOG.debug(行); [代码] 并且您可以看到它正在返回一些 json 的服务日志? Transfer-Encoding: chunked后,Server返回一个压缩流:“[0x1f][0x8b][0x8][0x0][0x0][0x0][0x0][0x0][0x0][ 0x3][0xac][0xb9][0xd7][0xce](等等)。这是json字符串 不错!您如何尝试使用 javadoc.io/doc/org.apache.httpcomponents/httpclient/latest/org/… ==> (new GzipDecompressingEntity(entity)).getContent()

以上是关于使用 HttpClient、REST 和 gzip 读取 JSON的主要内容,如果未能解决你的问题,请参考以下文章

HttpClient AutomaticDecompression 与 gzip 一起使用,而不是放气

从 HTTPClient 响应中解压 GZip 流

Apache Commons HttpClient 是不是支持 GZIP?

使用 PostAsync、HttpClient 和 Json 从 Windows Phone 8.1 调用 REST

使用HttpClient访问接口(Rest接口和普通接口)

如何使用基于 HttpClient 和 .net4 的 Rest-client 进行身份验证