【发布时间】:2013-07-22 21:34:33
【问题描述】:
我正在与一个客户端进行测试,该客户端向我发送了一个没有内容长度标头但有内容的 HTTP 请求。
如何在没有 contentlength 标头的帮助下提取此内容?
【问题讨论】:
-
请求是否包含
Transfer-Encoding:标头?
我正在与一个客户端进行测试,该客户端向我发送了一个没有内容长度标头但有内容的 HTTP 请求。
如何在没有 contentlength 标头的帮助下提取此内容?
【问题讨论】:
Transfer-Encoding: 标头?
为了完整起见,我保留了原始答案,但我一直在查看 HTTP RFC (2616) 第 4.3 节:
请求中消息体的存在通过在请求的消息头中包含 Content-Length 或 Transfer-Encoding 头字段来表示。如果请求方法的规范(第 5.1.1 节)不允许在请求中发送实体主体,则消息主体不得包含在请求中。服务器应该在任何请求上读取并转发消息体;如果请求方法不包含为实体主体定义的语义,则在处理请求时应该忽略消息主体。
因此,如果您没有内容长度,您必须有一个传输编码(如果您没有,您应该以 400 状态响应以指示错误请求或 411 (“所需长度”))。那时,你按照传输编码告诉你的去做:)
现在,如果您正在处理一个 servlet API(或类似的 HTTP API),它可能会为您处理所有这些 - 此时您可能能够使用下面的技术来阅读从流中提取,直到它不再产生数据,因为 API 会处理它(即它不仅仅是一个原始套接字流)。
如果您能向我们提供有关您的背景的更多信息,那将有所帮助。
原答案
如果没有内容长度,则表示内容一直持续到数据结束(当套接字关闭时)。
继续读取输入流(例如,将其写入 ByteArrayOutputStream 以存储它,或者可能是一个文件),直到 InputStream.read 返回 -1。例如:
byte[] buffer = new byte[8192];
ByteArrayOutputStream output = new ByteArrayOutputStream();
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1)
{
output.write(buffer, 0, bytesRead);
}
// Now use the data in "output"
编辑:正如 cmets 中所指出的,客户端可能正在使用分块编码。通常,您使用的 HTTP API 应该为您处理这个问题,但如果您处理的是原始套接字,则必须自己处理。
关于这是一个请求(因此客户端无法关闭连接)的观点很有趣 - 我认为客户端可以关闭发送部分,但我没有目前看不出它如何映射到 TCP 中的任何内容。我的低级网络知识可能不是这样。
如果这个答案“绝对没用”,我会删除它...
【讨论】:
如果这是一个响应,那么可以通过关闭连接来终止消息。但这不是一个选项,因为客户端仍然需要读取响应。
除了Content-Length:,其他确定内容长度的方法有:
Transfer-Encoding: chunked希望是前者,在这种情况下,请求应该如下所示:
POST /some/path HTTP/1.1 主机:www.example.com 内容类型:文本/纯文本 传输编码:分块 25 这是第一个块中的数据 1C 这是第二个 3 骗局 8 序列 0(无耻地从Wikipedia article盗取并修改为一个请求)
【讨论】:
【讨论】: