如何正确读取http请求?

时间:2016-09-07 15:13:13

标签: java http bufferedreader

如何使用InputStream读取HTTP请求?我曾经这样读过:

InputStream in = address.openStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
StringBuilder result = new StringBuilder();
String line;
while((line = reader.readLine()) != null) {
    result.append(line);
}
System.out.println(result.toString()); 

reader.readLine()可能被阻止,因为无法保证会到达null行。当然,我可以读取Content-Length标头,然后循环读取请求:

for (int i = 0; i < contentLength; i++) {
                int a = br.read();
                body.append((char) a);
    }

但是如果Content-Length设置得太大(我想可以手动设置它),br.read()将被阻止。 我尝试直接从InputStream读取字节,如下所示:

byte[] bytes = getBytes(is);

public static byte[] getBytes(InputStream is) throws IOException {

            int len;
            int size = 1024;
            byte[] buf;

            if (is instanceof ByteArrayInputStream) {
              size = is.available();
              buf = new byte[size];
              len = is.read(buf, 0, size);
            } else {
              ByteArrayOutputStream bos = new ByteArrayOutputStream();
              buf = new byte[size];
              while ((len = is.read(buf, 0, size)) != -1)
                bos.write(buf, 0, len);
              buf = bos.toByteArray();
            }
            return buf;
          }

但它永远等待。怎么办?

2 个答案:

答案 0 :(得分:2)

如果要实现HTTP服务器,则应根据HTTP规范检测请求的结束。维基 - https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol

首先,您应该阅读请求行,它始终是一行。 然后阅读所有请求标头。你读它们直到你有一个空行(即两行结尾 - <CR><LF>)。

在您拥有状态行和标题之后,您应该决定是否需要阅读正文或否,因为并非所有请求都可能包含正文 - summary table

然后,如果你需要一个正文,你应该解析你的标题(你已经得到)并获得Content-Length。如果是 - 只需从流中读取指定的字节数。 当缺少Content-Length时,长度以其他方式确定。分块传输编码使用块大小0来标记内容的结尾。没有Content-Length的身份编码会在套接字关闭之前读取内容。

答案 1 :(得分:-1)

创建一个扩展HttpServletRequestWrapper的请求包装器,它将覆盖getInputStream(),后者又返回具有安全读取方法的ServletInputStream。试试那个