即使没有contentlength标头,也可以从HTTP请求获取内容

时间:2011-03-03 07:52:52

标签: java http header

我正在向客户发送测试,该客户向我发送一个没有内容长度标题但有内容的HTTP请求。

如何在没有contentlength header的帮助下提取此内容?

3 个答案:

答案 0 :(得分:4)

我保留原始答案的完整性,但我一直在查看HTTP RFC (2616)部分4.3:

  

通过在请求的消息头中包含Content-Length或Transfer-Encoding头字段来指示请求中是否存在消息正文。如果请求方法的规范(第5.1.1节)不允许在请求中发送实体主体,则消息主体不得包含在请求中。服务器应该在任何请求上读取和转发消息体;如果请求方法不包含实体主体的定义语义,那么在处理请求时应该忽略消息体。

因此,如果您没有内容长度,必须拥有转移编码(如果您没有,则应以400状态回复以指示错误请求或411 (“需要长度”))。此时,您执行Transfer-Encoding告诉您的操作:)

现在,如果您正在处理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"

编辑:正如评论中指出的那样,客户端可能正在使用分块编码。通常,您正在使用的HTTP API应该为您处理此问题,但如果您正在处理原始套接字,则必须自己处理它。

关于这是一个请求(因此客户端无法关闭连接)是一个有趣的问题 - 我想到客户端可以关闭发送部分,但我不知道现在看看它是如何映射到TCP中的任何内容的。我的低级网络知识并非如此。

如果这个答案结果是“绝对没用”,我会删除它......

答案 1 :(得分:3)

如果这是响应,则可以通过关闭连接来终止消息。但这不是一个选项,因为客户端仍然需要阅读响应。

除了Content-Length:之外,确定内容长度的其他方法是:

  • Transfer-Encoding: chunked
  • 猜测

希望它是前者,在这种情况下,请求看起来应该是这样的:

POST /some/path HTTP/1.1
Host: www.example.com
Content-Type: text/plain
Transfer-Encoding: chunked

25
This is the data in the first chunk

1C
and this is the second one

3
con
8
sequence
0

(从Wikipedia article无耻地被盗并为请求而修改)

  • 每个块的格式为:十六进制编码长度,CRLF,数据,CRLF
  • 在最终的数据传输块之后出现了一个没有数据的零长度块
  • 在零长度块之后提供可选的额外HTTP标头
  • 在可选的HTTP标头出现另一个CRLF
  • 之后

答案 2 :(得分:0)