2015-10-19 140 views
0

我已經構建了一個使用Java套接字傳遞http請求和響應的Android代理服務器。編碼的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(); 

但是我得到ungzipping嘗試錯誤。

未知格式(幻數5448)

回答

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的支持,因此您需要查找或編寫一個庫來解壓縮 - 請參閱此其他堆棧溢出問題,以瞭解可能的起點:「Java SDCH compressor/decompressor」。

要解決您在使用GZIPInputStream時添加刺的問題的更新部分,最直接的問題是您應該只在HTTP響應頭結束後對流進行gunzip處理。最簡單的做法是等待「\ r \ n \ r \ n」來通過底層InputStream(而不是Reader),然後通過單個GZIPInputStream運行開始於下一個字節的數據。這應該可能適用於您給出的示例 - 我成功解碼了使用gunzip -c獲得的重播響應。爲了徹底,還有一些其他問題可以避免它成爲任意網站的一般解決方案,但我認爲這足以幫助您入門。 (一些例子:1)你可能會錯過一個「內容編碼」頭,因爲你將響應分成長度爲buf.length的塊。 2)使用分塊編碼的響應需要被分塊。 3)保持活躍的響應將需要跟蹤響應何時結束而不是等待流結束。)

+0

(quiestion updated)我嘗試了ungzipp,但它似乎並不是一個。那可能是那些其他的編碼嗎?我怎麼知道它是哪一個? –

+0

你需要gunzip只是響應。您將當前代碼中的標題包括在內,以便進行槍擊。嘗試跳過第一遍「\ r \ n \ r \ n」或「\ n \ n」進行第一遍實施。這不足以處理分塊編碼,但它可能足以讓你開始。 – twm