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

问题描述 投票:0回答:4

我使用 WinSck 创建了一个 C++ 应用程序,它实现了一个小型(仅处理我需要的一些功能)http 服务器。这用于使用 http 请求与外界进行通信。它可以工作,但有时请求无法正确处理,因为解析失败。现在我非常确定请求的格式正确,因为它们是由 firefox/chrome 或 perl/C#(具有 http 模块/dll)等主要 Web 浏览器发送的。

经过一些调试,我发现问题实际上是在接收消息时。当消息不止一部分时(不是在一次

recv()
调用中读取),有时解析会失败。我已经尝试了很多次来解决这个问题,但似乎没有什么足够可靠的。

我现在所做的是读入数据,直到找到指示标头结束的

"\r\n\r\n"
序列。如果在找到这样的序列之前
WSAGetLastError()
报告除 10035(连接关闭/失败)以外的其他内容,我会丢弃该消息。当我知道我拥有整个标头时,我会解析它并查找有关主体长度的信息。但是我不确定这些信息是否是强制性的(我认为不是),如果没有此类信息我该怎么办 - 这是否意味着不会有尸体?另一个问题是我不知道是否应该在主体后面寻找
"\r\n\r\n"
(如果它的长度大于零)。

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

注意:我知道有 http 服务器的实现。由于各种原因我想要自己的。是的,重新发明轮子是不好的,我也知道。

c++ http parsing winsock
4个回答
8
投票

如果您决定编写自己的解析器,我会采用 Zed Shaw 方法:使用 Ragel 状态机编译器并基于此构建您的解析器。如果你小心的话,Ragel 可以处理成块的输入。

老实说,我只是使用类似这样的东西

您的首选资源应该是 RFC 2616,它描述了 HTTP 1.1,您可以使用它来构建解析器。祝你好运!


3
投票

您可以尝试查看他们的代码,看看他们如何处理 HTTP 消息。

或者您可以查看规范,您应该使用消息长度字段。显然,只有有问题的浏览器才会在最后发送额外的 CRLF。


0
投票

无论如何,HTTP 请求有“ ” 位于请求标头末尾和请求数据之前(如果有),即使请求是“GET / HTTP/1.0 ”.

如果方法是“POST”,您应该在“之后读取尽可能多的字节” “,如内容长度字段中所指定。

所以伪代码是:

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

会有“ " 仅当内容包含它时才在内容之后。内容可以是二进制数据,它没有任何终止序列,获取其大小的一种方法是使用 Content-Length 字段。


-1
投票

HTTP

GET
/
HEAD
请求没有正文,
POST
请求也可以没有正文。您必须检查它是否是
GET
/
HEAD
,如果是,则您没有发送任何内容(正文/消息)。如果它是
POST
,请按照 规范中关于解析已知/未知长度的消息的说明进行操作,如 @gbjbaanb 所说。

© www.soinside.com 2019 - 2024. All rights reserved.