编码的Http请求/响应正文

时间:2015-10-19 09:34:43

标签: java android http proxy

我已经构建了一个Android代理服务器,使用Java Sockets传递http请求和响应。

代理正在运行,浏览器中的所有内容都通过它。但是,我可以阅读请求/回复,但他们的身体似乎被编码:

GET http://m.onet.pl/ HTTP/1.1
Host: m.onet.pl
Proxy-Connection: keep-alive
Cache-Control: max-age=0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Linux; Android 4.4.4; XT1039 Build/KXB21.14-L1.56) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.76 Mobile Safari/537.36
DNT: 1
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-GB,en;q=0.8,en-US;q=0.6,pl;q=0.4
Cookie: onet_ubi=201509221839473724130028; onetzuo_ticket=9AEDF08D278EC7965FF6A20BABD36EF0010012ED90FDD127C16068426F8B65A5D81A000000000000000050521881000000; onet_cid=dd6df83b3a8c33cd497d1ec3fcdea91b; __gfp_64b=2Mp2U1jvfJ3L9f.y6CbKfJ0oVfA7pVdBYfT58G1nf7T.p7; ea_uuid=201509221839478728300022; onet_cinf=1; __utma=86187972.1288403231.1442939988.1444999380.1445243557.40; __utmb=86187972.13.10.1445243557; __utmc=86187972; __utmz=86187972.1442939988.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none)

�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������

因此,在请求和响应中都有很多"���"发生。我没有找到任何关于http编码的信息。它是什么 ?我怎样才能正确阅读身体?

假设它可能是GZIPed消息,我试过:

while ((count = externalServerInputReader.read(buf, 0, buf.length)) != -1)
{
    String stream = new String(buf, 0 , count);
    proxyOutputStream.write(buf, 0, count);

    if (stream.contains("content-encoding: gzip")) {
        ByteArrayInputStream bais = new ByteArrayInputStream(buf);
        GZIPInputStream gzis = new GZIPInputStream(bais);
        InputStreamReader reader = new InputStreamReader(gzis);
        BufferedReader in = new BufferedReader(reader);

        String readed;
        while ((readed = in.readLine()) != null) {
            Log.d("Hello", "UnGzip: " + readed);
        }
    }
}
proxyOutputStream.flush();

但是我在尝试解压缩时遇到错误。

  

未知格式(幻数5448)

1 个答案:

答案 0 :(得分:2)

我尝试将您的样本请求保存到" / tmp / req"并使用cat /tmp/req | nc m.onet.pl 80重播它。服务器发送回gzip编码的响应,我可以从响应头content-encoding: gzip中找出。在响应是gzip编码的情况下,您可以使用java.util.zip.GZIPInputStream在Java中解压缩它。请注意,您示例中的用户代理也广告支持" deflate"和" sdch"因此,您也可以通过这些编码得到答复。 " deflate"可以使用java.util.zip.InflaterInputStream解压缩编码。我不知道对sdch的任何内置支持,所以你需要找到或编写一个库来解压缩 - 请参阅另一个Stack Overflow问题以寻找可能的起点:" Java SDCH compressor/decompressor "

要解决您在使用GZIPInputStream添加了一个问题的更新部分,最直接的问题是您应该只在HTTP响应标头结束后对该流进行gunzip。最简单的方法是等待" \ r \ n \ r \ n"遇到底层的InputStream(不是Reader),然后通过单个GZIPInputStream运行从下一个字节开始的数据。这可能适用于您给出的示例 - 我成功解码了使用gunzip -c获得的重放响应。为了彻底,还有一些其他问题会阻止它作为任意网站的一般解决方案,但我认为这足以让你开始。 (一些例子:1)你可能会错过"内容编码"标头,因为您将响应拆分为长度为buf.length的块。 2)使用分块编码的响应需要被去块。 3)保持活动响应将需要您跟踪响应何时结束而不是等待流结束。)