2015-10-19 5 views
0

Я создал прокси-сервер Android, передающий HTTP-запрос и ответы с использованием 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-кодировании. Что это ? Как я могу правильно прочитать тело?


Предполагая, что это может быть сообщение я являющегося файлом пробовал:

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 с помощью java.util.zip.GZIPInputStream. Обратите внимание, что пользовательский агент в вашем примере также поддерживает рекламу «deflate» и «sdch», поэтому вы также можете получить ответы с этими кодировками. Кодирование «deflate» может быть распаковано с помощью java.util.zip.InflaterInputStream. Я не знаю какой-либо встроенной поддержки sdch, поэтому вам нужно будет найти или написать библиотеку для ее распаковки - см. Этот другой вопрос переполнения стека для возможной отправной точки: «Java SDCH compressor/decompressor».

Чтобы рассмотреть обновленную часть вашего вопроса, в которой вы добавили удар при использовании GZIPInputStream, самая непосредственная проблема заключается в том, что вы должны уничтожить поток только после того, как заголовки ответов HTTP закончились. Самое простое - подождать, когда «\ r \ n \ r \ n» попадет в базовый InputStream (а не Reader), а затем запустит данные, начиная с следующего байта, через один GZIPInputStream. Это, вероятно, должно работать для примера, который вы дали - я успешно декодировал повторный ответ, который я получил, используя gunzip -c. Для тщательности есть некоторые другие проблемы, которые не позволят этому работать как общее решение для произвольных веб-сайтов, но я думаю, этого будет достаточно, чтобы вы начали. (Некоторые примеры: 1) вы можете пропустить заголовок «content-encoding», потому что вы разделяете ответ на куски длины buf.length. 2) Ответы, в которых используется закодированное кодирование, должны быть дезактивированы. 3) Реакции Keep-alive потребуют, чтобы вы отслеживали, когда ответ заканчивается, а не ждать окончания потока.)

+0

(quiestion обновлено) Я попытался выполнить ungzipp, но это не похоже. Могут ли быть другие кодировки? Как я могу узнать, кто это? –

+0

Вы должны уничтожить только ответ. Вы включаете заголовки в свой текущий код для того, что застревает. Попробуйте перейти к первому «\ r \ n \ r \ n» или «\ n \ n» для реализации первого прохода. Этого будет недостаточно, чтобы обработать закодированное кодирование, но этого может быть достаточно, чтобы вы начали. – twm