即使没有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节 。