检测HTTP请求正文的结束

检测HTTP请求正文的结束,http,Http,我正在编写自己的HTTP客户端和服务器,希望客户端在请求中包含一个可选的主体。在服务器端,我希望在发送HTTP响应之前读取整个正文。我的问题是在服务器上,我怎么知道我读了整个身体 即使在这种情况下,我同时控制客户机和服务器,我还是在寻找一种“标准”方法。然而,由于内容长度是可选的,我想要一个不需要它的方法。如果客户端关闭连接,则很容易读取所有可用数据,但是客户端需要保持连接打开以等待响应,因此此方法不起作用 我所能想到的就是了解身体的形式和检测终结者(例如,)。理想情况下,我不想要求这些知识 有

我正在编写自己的HTTP客户端和服务器,希望客户端在请求中包含一个可选的主体。在服务器端,我希望在发送HTTP响应之前读取整个正文。我的问题是在服务器上,我怎么知道我读了整个身体

即使在这种情况下,我同时控制客户机和服务器,我还是在寻找一种“标准”方法。然而,由于内容长度是可选的,我想要一个不需要它的方法。如果客户端关闭连接,则很容易读取所有可用数据,但是客户端需要保持连接打开以等待响应,因此此方法不起作用

我所能想到的就是了解身体的形式和检测终结者(例如,
)。理想情况下,我不想要求这些知识


有没有一种方法我忽略了?

当你说“内容长度是可选的”时,我想你是在阻止自己使用最明显的选择

从HTTP规范

应用程序应使用此字段 指示传输线的传输长度 消息正文,除非 第节中的规则禁止 4.4

如果您知道长度,而且听起来您会知道,请在Content-length标题中指定它,然后使用它,因为规范基本上要求您这样做(假设您所做的任何事情都不违反中提到的规则)。

简单的方法:使用HTTP 1.0并要求内容长度

为了与HTTP/1.0应用程序兼容,包含消息正文的HTTP/1.1请求必须包含有效的内容长度头字段,除非已知服务器符合HTTP/1.1。如果请求包含消息正文且未给出内容长度,则服务器应在无法确定消息长度时以400(错误请求)响应,或在希望坚持接收有效内容长度时以411(所需长度)响应。
假设您希望您的客户机与其他服务器一起工作,并且服务器与其他客户机一起工作,那么您的服务器就不能期望得到很好的处理

有两种方法可以判断身体何时结束。它们都不需要您建议的正文内容类型的知识(例如,不要费心寻找远远超出HTTP协议的

  • 如果客户机发送带有
    传输编码:Chunked
    的消息,则需要解析稍微复杂的代码。在这件事上你真的没有太多的选择——如果客户端以这种格式发送,你就必须接收它。当客户端使用这种方法时,可以通过长度为0的块检测正文的结尾
  • 如果客户端改为发送
    内容长度
    ,则必须使用该长度
  • 正如您所建议的,检测结束的第三种方法——当连接关闭时——只适用于响应,而不适用于请求(因为此时无法发送响应)


    i、 e.您有权坚持使用
    传输编码:分块
    内容长度
    ,因此您不必担心在任何其他情况下确定长度

    我添加了另一个答案,主要是因为我没有足够的代表评论mgiuca。我知道这个问题有点老了,但还没有确定的答案

    正如前面提到的,需要考虑的主要问题是,您的服务器与无法控制的其他服务器交互,这意味着您根本不知道他们将发送什么,并且必须准备好管理通过该网关的任何内容。考虑到这一点,坚持标准和常规做法可能是最佳选择

    如果客户端发送一个“Content-Length”头,服务器必须解析它并使用它来确定请求的结束。如果没有这样的头,但存在“传输编码:分块”头,那么服务器必须能够解析分块请求(来自mgiuca的答案)。最后,如果两者都不存在,“连接结束”表示请求结束

    我认为您忽略了一个事实,即客户端可以结束连接,但仍然可以从服务器获得响应。我是说,“结束连接”是什么意思?请记住,HTTP是(通常)通过TCP传输的应用层协议。探索TCP的功能(特别是其协议)会揭示一些有趣的信息:

    • 要主动结束连接,客户端发送一个带有FIN标志的数据包,这是四向握手的一部分。由于终止协议尚未完成,连接仍被视为打开
    • 服务器接收此数据包并通知客户端so(ACKpackage)。服务器现在知道客户端将不再传输数据
    • 客户端进入FIN_WAIT2状态,等待来自服务器的带有FIN标志的数据包正确关闭连接
    但是它在那里!客户端已经通知他想要结束连接,服务器也知道,但是客户端仍然打开了连接(他还没有关闭连接,因为他没有收到FIN数据包)。服务器现在响应请求,然后正确关闭连接。需要注意的是,客户端将ACK每个服务器数据包,并附加一个RST标志,告诉服务器他仍然希望FIN关闭连接

    当服务器完成时(在我们的小示例中,在发送HTTP响应之后),他会关闭自己一侧的连接,发送FIN数据包。客户端在收到消息时关闭其服务器端,并用确认通知服务器

    另一方面,我不知道您在什么环境下编程,但大多数情况下,您最终会调用s
    If a request contains a message-body and a Content-Length is not given, 
    the server SHOULD respond with 400 (bad request) if it cannot determine
    the length of the message, or with 411 (length required) if it wishes 
    to insist on receiving a valid Content-Length.