代码之家  ›  专栏  ›  技术社区  ›  PeterK

如何正确解析传入的HTTP请求

  •  5
  • PeterK  · 技术社区  · 14 年前

    我用WiSCK创建了一个C++应用程序,它有一个小的(只处理我需要的几个特性)HTTP服务器。这用于使用http请求与外部世界通信。它可以工作,但有时请求没有得到正确处理,因为解析失败。现在我很确定请求的格式是正确的,因为它们是由主要的web浏览器发送的,比如firefox/chrome或perl/C#(它们有http模块/dll)。

    经过一番调试,我发现问题其实是在接收消息。当信息包含多个部分时(不是一个部分读取) recv() 有时解析失败。关于如何解决这个问题,我做了很多尝试,但似乎没有什么是足够可靠的。

    "\r\n\r\n" 指示标头结尾的序列。如果 WSAGetLastError() 在发现这样的序列之前,报告10035以外的内容(连接关闭/失败),我将丢弃该消息。当我知道我有整个头,我解析它,并寻找有关正文长度的信息。然而,我不确定这些信息是否是强制性的(我认为不是),如果没有这些信息我该怎么办-这是否意味着没有尸体?另一个问题是我不知道我是否应该找一个 “\r\n\r\n” 在主体之后(如果其长度大于零)。

    有人知道如何可靠地解析http消息吗?

    4 回复  |  直到 14 年前
        1
  •  3
  •   gbjbaanb    14 年前

    或者你可以看看 the spec ,有 message length 应该使用的字段。显然,只有有缺陷的浏览器才会在最后发送额外的crlf。

        2
  •  8
  •   Homme Zwaagstra Jack Kelly    12 年前

    如果你开始编写自己的解析器,我会 Zed Shaw 方法:使用 Ragel 并在此基础上构建解析器。如果你小心的话,Ragel可以处理成堆的输入。

    不过,老实说,我只是想 something like this

    你的搜索资源应该是 RFC 2616 ,它描述了HTTP1.1,您可以使用它来构造解析器。祝你好运!

        3
  •  0
  •   Abyx    14 年前

    如果方法是“POST”,则应读取“Content Length”字段中指定的“\r\n\r\n”后面的字节数。

    所以伪代码是:

    read_until(buf, "\r\n\r\n");
    if(buf.starts_with("POST")
    {
       contentLength = regex("^Content-Length: (\d+)$").find(buf)[1];
       read_all(buf, contentLength);
    }
    

    仅当内容包含“\r\n\r\n”时,内容后面才会有“\r\n”。内容可以是二进制数据,它没有任何终止序列,获取其大小的一种方法是使用内容长度字段。

        4
  •  -1
  •   aularon    14 年前

    超文本传输协议 GET / HEAD POST 请求也可以没有正文。你得检查一下是不是 得到 / ,如果是,则没有发送内容(正文/消息)。如果它是一个 ,按要求执行 specs say about parsing a message of known/unknown length