如何正确读取http请求?
如何使用InputStream读取HTTP请求?我用这样来阅读:如何正确读取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);
}
但如果内容长度设置得过大(我想这可以手动设置目的),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;
}
但它永远等待。做什么?
如果你正在实现HTTP服务器,你应该根据HTTP规范检测请求的结束。 Wiki - https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol
首先,您应该阅读请求行,它始终是单行。 然后阅读所有请求标题。你阅读它们,直到你有一个空行(即两行结尾 - <CR><LF>
)。
之后,你有一个状态栏和标题,你应该决定你需要阅读的身体或没有,因为不是所有的请求可能有身体 - summary table
然后,如果你需要一个身体,你应该分析你的头(你已经得到)并获得Content-Length。如果是 - 只要从指定的流中读取尽可能多的字节。 当内容长度缺失时,长度以其他方式确定。分块传输编码使用块大小为0来标记内容的结尾。无内容长度的身份编码将读取内容,直到套接字关闭。
创建一个扩展HttpServletRequestWrapper的请求包装器,它将覆盖getInputStream(),该getInputStream()返回ServletInputStream,该ServletInputStream具有安全读取方法。试试
它与servlet无关。 – Tony
为什么不能保证能够达到'null'行?根据文档,如果已经到达流的末尾,它将返回'null'。所以如果连接被关闭,你会在读完最后一行后得到空值。 –
我可以达到的第一个空行是头和请求体之间的分隔符(如表单数据)。但身体后面没有空线。做什么? – Tony
也许你得到一个空的身体请求? –