使用自定义Web代理时,HTTP响应未接收到所有数据

时间:2016-03-01 18:19:44

标签: java sockets http proxy

所以我正在创建一个抓取HTTP请求的Web代理,确保GET / POST / HEAD大写,并修复第一行中的路径:

-------------------
------REQUEST------
-------------------
GET http://boundlessecho.com/story.html HTTP/1.1
Host: boundlessecho.com
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 (Macintosh; Intel Mac OS X 10_11_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.116 Safari/537.36
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8


Port 80 Connected
-------------------
---FIXED REQUEST---
-------------------
GET /story.html HTTP/1.1
Host: boundlessecho.com
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 (Macintosh; Intel Mac OS X 10_11_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.116 Safari/537.36
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8

然后将此数据发送到DNS请求之后指定的服务器,该请求获取主机名和端口号(100次中的99次,未指定端口,因此它将转到端口80,这是默认的HTTP端口)。

之后,我将HTTP响应从服务器发送回客户端/浏览器;但是,很多时候,它会在接收HTTP响应部分时被捕获。

BufferedReader feedback = new BufferedReader(new InputStreamReader(requestedServer.getInputStream()));
BufferedWriter showData = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream(), "UTF-8"));

String line;
String header = "";

while (!(line = feedback.readLine()).equals("")) {
    header += line + "\n";
}

int length = getLengthOfData(header);

showData.write(header, 0, header.length());
showData.write("\n", 0, 1);
showData.flush();

DataInputStream getBodyData = new DataInputStream(requestedServer.getInputStream());
DataOutputStream sendBodyData = new DataOutputStream(clientSocket.getOutputStream());

if (length != -1) {
    byte[] b = new byte[length];
    getBodyData.read(b, 0, length);
    sendBodyData.write(b, 0, length);
    sendBodyData.flush();
}

sendData.close();
showData.close();
feedback.close();
sendBodyData.close();
getBodyData.close();

查找内容长度的方法:

// Simply returns the Content-Length as an integer
public int getLengthOfData(String header) {

    if (header.indexOf("Content-Length:") == -1) {
        return -1;
    }

    return Integer.parseInt(header.substring(header.indexOf("Content-Length:") + 16, header.indexOf("\n", header.indexOf("Content-Length:"))));

}

有谁知道为什么它会卡在feedback.readLine()上,或者我的代码中的其他地方是否存在导致此问题的问题?

注意:它只会卡在某些请求上。有些请求有效!

注2:代码从原始帖子更新。

注3:代码再次更新。

1 个答案:

答案 0 :(得分:2)

您对回复的阅读不完整。您需要首先阅读响应标头(读取直到您到达表示标头末尾的CRLF CRLF对),然后您需要分析标头以了解是否以及如何读取任何其他数据。 HEAD个回复以及所有1xx204304回复都没有正文内容,因此请勿尝试为其阅读正文。其他任何东西都有一个正文,其长度取决于Transfer-EncodingContent-LengthContext-Type响应标头的特定值,因此您需要查看它们并采取相应的行动。< / p>

阅读RFC 2616 Section 4.4 "Message Length"了解更多详情以及您必须遵循的确切规则。

基本上,您必须实现以下逻辑:

Read and parse HTTP headers
if not successful:
    throw error
if response can contain message body:
    if HTTP version is 1.1+ and Transfer-encoding is not identity:
        while true:
            read line, extract delimited ASCII hexadecimal, the chunk size
            if not successful:
                throw error
             if chunk size is 0:
                break while loop
             read chunk size number of bytes
        read and parse trailing HTTP headers
    else if Content-Length is specified:
        read Content-Length number of bytes
    else if Content-Type is "multipart/byteranges":
        read and parse MIME-encoded chunks until terminating MIME boundary is reached
    else:
        read until connection is closed