Lazy decompressing of HttpEntity.getContent()

最近在做项目在写 Http post  的时候发现一个有趣的问题。

使用 Apache 的 HttpComponents 工具开发。

当发起 http post 请求的时候,返回的 HttpResponse 的内容是空的(实际上是有数据的),也就是在bebug的时候看到HttpResponse 的entity中 “content=null” 的字样,人傻了好吧,步骤都OK,代码给没问题,但是就是空!然而还有那么一段代码(代码是直接用的官网的例子),导致一直无法获取数据,如下:

CloseableHttpResponse response = httpclient.execute(request);
try {
    HttpEntity entity = response.getEntity();
    if (entity != null) {
        long len = entity.getContentLength();
        if (len != -1 ) {  // 问题就出在这里
        result = EntityUtils.toString(entity, "utf-8");
        System.out.println("postXml返回result:" + result);
        }
    }
    } finally {
     response.close();
}

解析一下:当content==null时,len是等于 -1 的,由于在获取的HttpResponse 的 entity 中 content  = null, 所以代码标明问题的地方(len!= -1)不成立,直接跳过,导致无法进入到 if 代码块中。

解决办法:把 if ( len != -1 ) 这个判断代码去掉,这样直接调用 EntityUtils.toString(entity, "utf-8"); 有趣的东西来了,当调用这句代码的时候 HttpResponse 的 entity 中 content 就有数据了。。。

后面查找资料的时候才知道是怎么回事,记录一下。在apache的论坛下有这样的一个描述

In 4.3, DecompressingEntity is used for decompressing entity of http response. When we call DecompressingEntity.getContent(), an new DeflateInputStream or GZIPInputStream will be created, and the header of compressing part will be read and checked.

InputStream decorate(final InputStream wrapped) throws IOException

{ return new GZIPInputStream(wrapped); }

In some cases, we don't really need to decompress it. For example, in "http://baike.baidu.com/search/word?word=httpclient&pic=1&sug=1&enc=utf8" the response state code is 302, it contains header "Content-Encoding:gzip" but without any entity data (It occurs sometimes). In RedirectExec.execute(), we don't read the entity, but in the end, it try to close inputstream by EntityUtils.consume(response.getEntity()). When we call entity.getContent() in EntityUtils.consume(response.getEntity()), an EOFException will be thrown and the redirect can not continue.

In this case, we don't care about the real entity – even if the compress format is not right.

In my opinion, the format should be created and checked ONLY when we need to read the content but not just when closing it. So I wrote LazyDecompressingInputStream as a wrapper and create the DecompressingStream until read() method is called. Then more website will be supported.

 引用来源https://issues.apache.org/jira/browse/HTTPCLIENT-1432

文章讲了当entity的内容需要被读取的时候才会去创建输入流,同时作者也讲述了他这样做的目的是为了避免某些情况的异常发生支持更多的网站

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值