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

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

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

我保留了原始答案的完整性,但我刚刚查看了HTTP RFC(2616)第4.3节:

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

因此,如果您没有内容长度,则必须具有Transfer-Encoding(如果您没有,则应以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中的任何内容在这一刻。 我的低级网络知识并非如此。

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

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

Content-Length: ,确定内容长度的其他方法有:

  • Transfer-Encoding: chunked
  • 猜测

希望它是前者,在这种情况下,请求应该如下所示:

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

 25
这是第一个块中的数据

 1C
这是第二个

 3
 CON
 8
序列
 0

(从维基百科文章中无耻地窃取并根据请求进行了修改)

  • 每个块的forms为:hex编码长度,CRLF,数据,CRLF
  • 在最终的数据携带块之后出现一个没有数据的零长度块
  • 零长度块之后是可选的额外HTTP头
  • 在可选的HTTP标头出现另一个CRLF之后

请参见HTTPbis第1部分,第3.3节 。