解析HttpResponse InputStream 乱码问题

运行环境:Docker,JDK8,Spring Boot,Spring Cloud,Zuul

在微服务网关编写的过程中,需要解析网关转发后响应的报文信息,需要对 RequestContext.getCurrentContext().getResponseDataStream() 的流数据进行解析。

在本地环境及测试环境均运行正常,而在正式环境则出现响应解析乱码的问题。

 

尝试使用

InputStream stream = ctx.getResponseDataStream();

bytes = StreamUtils.copyToByteArray(stream);

log.info(new String(bytes,"utf8"));
log.info(new String(bytes,"gbk"));

均展示乱码。而同样的代码在本地及测试均正常。

无奈将响应头打印出来,如下:

X-Zuul-Service: http://***:***/***/ ,Server: Apache-Coyote/1.1 ,Content-Type: text/html;charset=UTF-8 ,Date: Mon, 19 Nov 2018 12:16:25 GMT ,Content-Encoding: gzip ,Vary: Accept-Encoding ,Transfer-Encoding: chunked ,Connection: Keep-alive ,Via: 1.1 ID-0002262016416074 uproxy-9 ,

重点在于 Content-Encoding: gzip

Accept-Encoding 和Content-Encoding是HTTP中用来对采用哪种编码格式传输正文进行协定的一对头部字段。

工作原理如下:

1.首先浏览器(也就是客户端)发送请求时,通过Accept-Encoding带上自己支持的内容编码格式列表;
2.服务端在接收到请求后,从中挑选出一种用来对响应信息进行编码,并通过Content-Encoding来说明服务端选定的编码信息
3.浏览器在拿到响应正文后,依据Content-Encoding进行解压。

服务端也可以返回未压缩的正文,但这种情况不允许返回Content-Encoding

内容编码的目的是优化传输内容的大小,通俗的讲就是尽心压缩。一般经过gzip压缩过的文本响应,只有原始大小的1/4(这个数据我现在还不确定)。对于文本类响应是否开启了内容压缩,是我们做性能优化时首先要检查的重要项目;而对于JPG/PNG这类本身已经高度压缩过的二进制文件,不推介开启内容压缩,效果几乎微乎其微,还浪费cpu

内容的编码针对的只是传输正文。在HTTP/1中,头部始终是以ASCII文本传输,没有经过任何压缩。不过这个问题在HTTP/2中已经解决。

内容编码使用特别广泛,理解起来也特别简单,但是要注意的是不要把它与HTPP中的另外一个概念:传输编码Transfer-Encoding搞混即可。

引用:HTTP 协议中的Content-Encoding - 枫秀天涯的博客 - CSDN博客

 

所以乱码的根本原因是响应数据被压缩,直接解析理所当然的就会乱码了。普通的InputStream 解析可以参考下面的引用:

引用:HttpCLient实现对被GZip压缩过的Response进行解压 - 苏文星 - CSDN博客

 

参考上述引用,自己编写在Zuul进行处理的代码逻辑如下:

InputStream stream = ctx.getResponseDataStream();
byte[] bytes;

if(ctx.getResponseGZipped()) {
	log.info(" it is gzipped ");
	GZIPInputStream gzipInputStream = new GZIPInputStream(stream);
	bytes = StreamUtils.copyToByteArray(gzipInputStream);
} else {
	log.info(" it isn't gzipped ");
	bytes = StreamUtils.copyToByteArray(stream);
}

body = new String(bytes,"utf8");
ctx.setResponseBody(body);

最终成功解决问题。

至于为什么会出现这种问题,可能是因为正式环境的F5负载,或者是HA负载的过程中,给请求添加了额外的头部数据。

本地无负载,测试环境为HA负载,正式环境有F5负载与HA负载。

 

展开阅读全文
©️2020 CSDN 皮肤主题: 大白 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值