在项目中使用retrofit和OkHttp后,服务端返回的数据将被压缩,OkHttp无法解析数据
故障诊断
过去,通过调用API服务端分发的所有数据都是gzip压缩的,但响应头中没有内容编码: gzip头。 以前,使用HttpURLConnection类时,我们直接编写解压缩代码来解压缩响应数据流(后面有代码)。
调查OkHttp的说明后,OkHttp实际上会根据是否有这个gzip的头自动判断是否需要解压缩响应数据。
基于此,我让服务端在response的header中添加了response.add header (' content-encoding ',' gzip ' ) )。 头儿,这样安卓方面的问题解决了。 但是,在iOS端发生了数据无法解压缩的错误。 具体错误的说明是,他们对返回的数据进行gzip解压缩时,发现无法顺利解压缩。 在进行故障诊断时,他们获得的response数据已经解压缩,通过调用自己实现的解压缩方法发现数据异常。 因此,服务端在添加gzip报头后,初步判断分发的数据未压缩。
调试过程
根据这一观点,我们的服务端去check为什么戴上头后数据没有压缩? 在Android端使用FaceBook的Stetho工具(Chrome )进行网络捕获时,发现数据确实没有压缩。
与服务端联系了一下午一夜没有结果后,服务端同学提出数据压缩可靠。 debug打的log数据已经得到了证明。 另外,发现Chrome在网络调试时会自动解压缩gzip头部的数据。
在此基础上,我在安卓上使用HttpURLConnection类手动调试。 代码如下。
intresponsecode=httpurl connection.getresponse code (;
if (响应代码==httpurl connection.http _ ok ) {
//un gzip
in=httpurl connection.get inputstream (;
bytearrayoutputstreambytearrayoutputstream=newbytearrayoutputstream (
int len1;
byte[] buffer1=new byte[1024];
while((len1=in.read ) buffer1)!=-1 ()
bytearray output stream.write (buffer 1,0,len1);
}
in.close (;
byteArrayOutputStream.close (;
finalstringstr1=new string (bytearray output stream.to bytearray )、' utf-8 ' );
Debug.i_MrFu ('未解压缩的数据=' str1);
//do gzip
in=newgzipinputstream (httpurl connection.get inputstream ();
bytearrayoutputstreamarrayoutputstream=newbytearrayoutputstream (
int len;
byte[] buffer=new byte[1024];
wile((len=in.read ) ) buffer )!=-1 ()
阵列输出流. write (buffer,0,len );
}
in.close (;
阵列输出流. close (;
finalstringstr=new string (array output stream.to bytearray ()、' utf-8 ' );
Debug.i_MrFu ('解压缩的数据=' str );
}
最后,我们发现确实分发的数据是压缩的。 此时,iOS也发现了问题。 iOS的NSURLConnection类对包含gzip标头的响应执行自动解压缩。 所以他们调试的时候得到的byte[]其实已经解压了。 看看这个issue : nsurlconnection/nsurlrequestgzipsupport!
结论
Chrome在网络调试时自动确定是否对gzip标头进行解压缩
iOS中的NSURLConnection类自动确定是否对gzip标头进行解压缩
OkHttp确定是否对gzip头部自动解压缩
因为HttpURLConnection必须自己做所有的事情,所以必须使用GZIPInputStream自己写解压缩代码的do gzip注释。 上述方法
应该早点在HttpURLConnection上进行调试输出数据流….工具(Stetho )在这个时候用得太多了(自动解压缩了)。
即使看到了,也只有不断挖掘事情的真相,而不是事情的真相
(责任编辑:模板最多)