如何使用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;
}
但它永远等待。怎么办?
答案 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。试试那个