解析类型定义:
enum http_parser_type { HTTP_REQUEST, HTTP_RESPONSE, HTTP_BOTH };
解析函数声明:
void http_parser_init(http_parser *parser, enum http_parser_type type);
void http_parser_settings_init(http_parser_settings *settings);
size_t http_parser_execute(http_parser *parser,
const http_parser_settings *settings, const char *data, size_t len);
说明:
http_parser_execute解析请求或应答报文,并返回实际解析的报文长度,此长度只代表解析一个完整报文扫描的长度,并不表示接收完整报文成功,完整报文的判断需要依赖on_message_complete回调。
如果发生错误,可以检查parser->http_errno的数值。
回调函数集合设定:
struct http_parser_settings {
http_cb on_message_begin; // 消息开始回调
http_data_cb on_url; // url回调
http_data_cb on_status; // 状态回调
http_data_cb on_header_field; // 字段名称回调
http_data_cb on_header_value; // 字段值回调
http_cb on_headers_complete; // 头部结束回调
http_data_cb on_body; // 消息体回调
http_cb on_message_complete; // 消息结束回调
http_cb on_chunk_header; // 收到chunk响应回调,已接收的chunk数据长度保存在parser->content_length
http_cb on_chunk_complete; // chunk响应结束回调
};
回调函数定义:
typedef int (http_data_cb) (http_parser, const char at, size_t length);
typedef int (http_cb) (http_parser*);
使用方法:
将源码中的http_parser.h和http_parser.c直接拷贝到工程目录下,随工程一起编译,同时支持windows及linux。
解析请求:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdint.h>
#include <string>
#include <map>
#include "http_parser.h"
// 用于解析的全局变量
bool bParsed = false;
std::map<std::string, std::string> mapHeadField;
std::string strUrl;
std::string strStatus;
std::string strBody;
std::string strFieldTmp;
// 用于解析的回调函数
int onMessageBegin(http_parser* pParser);
int onHeaderComplete(http_parser* pParser);
int onMessageComplete(http_parser* pParser);
int onURL(http_parser* pParser, const char *at, size_t length);
int onStatus(http_parser* pParser, const char *at, size_t length);
int onHeaderField(http_parser* pParser, const char *at, size_t length);
int onHeaderValue(http_parser* pParser, const char *at, size_t length);
int onBody(http_parser* pParser, const char *at, size_t length);
int main(int argc, char* argv[])
{
// 待解析的请求报文
std::string strHttpReq = "";
strHttpReq += "POST /uploaddata HTTP/1.1\r\n";
strHttpReq += "Host: 127.0.0.1:8080\r\n";
strHttpReq += "Accept: */*\r\n";
strHttpReq += "Content-Length: 70\r\n";
strHttpReq += "Content-Type: application/json\r\n";
strHttpReq += "\r\n";
strHttpReq += "{\"DeviceID\":\"12345678\",\"LowPressure\":80,\"HighPressure\":120,\"Pulse\":90}";
http_parser httpParser;
http_parser_settings httpSettings;
// 初使化解析器及回调函数
http_parser_init(&httpParser, HTTP_REQUEST);
http_parser_settings_init(&httpSettings);
httpSettings.on_message_begin = onMessageBegin;
httpSettings.on_headers_complete = onHeaderComplete;
httpSettings.on_message_complete = onMessageComplete;
httpSettings.on_url = onURL;
httpSettings.on_status = onStatus;
httpSettings.on_header_field = onHeaderField;
httpSettings.on_header_value = onHeaderValue;
httpSettings.on_body = onBody;
// 解析请求
int nParseBytes = http_parser_execute(&httpParser, &httpSettings, strHttpReq.data(), strHttpReq.size());
printf("http_parser_execute => parsebytes:[%d] parseok:[%d] \n", nParseBytes, bParsed);
// 解析成功,打印解析结果
if (bParsed)
{
printf("url: [%s] \n", strUrl.c_str());
printf("status: [%s] \n", strStatus.c_str());
printf("heads: \n");
for (std::map<std::string, std::string>::iterator iter = mapHeadField.begin(); iter != mapHeadField.end(); ++iter)
{
printf("\t %s : %s \n", iter->first.c_str(), iter->second.c_str());
}
printf("body: [%s] \n", strBody.c_str());
}
return 0;
}
int onMessageBegin(http_parser* pParser)
{
printf("@onMessageBegin call \n");
bParsed = false;
return 0;
}
int onHeaderComplete(http_parser* pParser)
{
printf("@onHeaderComplete call \n");
return 0;
}
int onMessageComplete(http_parser* pParser)
{
printf("@onMessageComplete call \n");
bParsed = true;
return 0;
}
int onURL(http_parser* pParser, const char *at, size_t length)
{
printf("@onURL call, length:[%d] \n", length);
strUrl.assign(at, length);
printf("@onURL url:[%s] \n", strUrl.c_str());
return 0;
}
int onStatus(http_parser* pParser, const char *at, size_t length)
{
printf("@onStatus call, length:[%d] \n", length);
strStatus.assign(at, length);
printf("@onStatus status:[%s] \n", strStatus.c_str());
return 0;
}
int onHeaderField(http_parser* pParser, const char *at, size_t length)
{
printf("@onHeaderField call, length:[%d] \n", length);
strFieldTmp.assign(at, length);
printf("@onHeaderField field:[%s] \n", strFieldTmp.c_str());
return 0;
}
int onHeaderValue(http_parser* pParser, const char *at, size_t length)
{
printf("@onHeaderValue call, length:[%d] \n", length);
std::string strValue(at, length);
printf("@onHeaderValue value:[%s] \n", strValue.c_str());
mapHeadField.insert( std::make_pair(strFieldTmp, strValue) );
return 0;
}
int onBody(http_parser* pParser, const char *at, size_t length)
{
printf("@onBody call, length:[%d] \n", length);
printf("@onBody recv:[%s] \n", std::string(at, length).c_str());
strBody.append(at, length);
return 0;
}
执行输出如下:
@onMessageBegin call
@onURL call, length:[11]
@onURL url:[/uploaddata]
@onHeaderField call, length:[4]
@onHeaderField field:[Host]
@onHeaderValue call, length:[14]
@onHeaderValue value:[127.0.0.1:8080]
@onHeaderField call, length:[6]
@onHeaderField field:[Accept]
@onHeaderValue call, length:[3]
@onHeaderValue value:[*/*]
@onHeaderField call, length:[14]
@onHeaderField field:[Content-Length]
@onHeaderValue call, length:[2]
@onHeaderValue value:[70]
@onHeaderField call, length:[12]
@onHeaderField field:[Content-Type]
@onHeaderValue call, length:[16]
@onHeaderValue value:[application/json]
@onHeaderComplete call
@onBody call, length:[70]
@onBody recv:[{"DeviceID":"12345678","LowPressure":80,"HighPressure":120,"Pulse":90}]
@onMessageComplete call
http_parser_execute => parsebytes:[186] parseok:[1]
url: [/uploaddata]
status: []
heads:
Accept : */*
Content-Length : 70
Content-Type : application/json
Host : 127.0.0.1:8080
body: [{"DeviceID":"12345678","LowPressure":80,"HighPressure":120,"Pulse":90}]
解析响应:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdint.h>
#include <string>
#include <map>
#include "http_parser.h"
// 用于解析的全局变量
bool bParsed = false;
std::map<std::string, std::string> mapHeadField;
std::string strUrl;
std::string strStatus;
std::string strBody;
std::string strFieldTmp;
// 用于解析的回调函数
int onMessageBegin(http_parser* pParser);
int onHeaderComplete(http_parser* pParser);
int onMessageComplete(http_parser* pParser);
int onURL(http_parser* pParser, const char *at, size_t length);
int onStatus(http_parser* pParser, const char *at, size_t length);
int onHeaderField(http_parser* pParser, const char *at, size_t length);
int onHeaderValue(http_parser* pParser, const char *at, size_t length);
int onBody(http_parser* pParser, const char *at, size_t length);
int main(int argc, char* argv[])
{
// 待解析的响应报文
std::string strHttpRes = "";
strHttpRes += "HTTP/1.1 200 OK\r\n";
strHttpRes += "Cache-Control: private\r\n";
strHttpRes += "Content-Type: application/json; charset=utf-8\r\n";
strHttpRes += "Server: Microsoft-IIS/8.0\r\n";
strHttpRes += "X-AspNetMvc-Version: 5.2\r\n";
strHttpRes += "X-AspNet-Version: 4.0.30319\r\n";
strHttpRes += "X-Powered-By: ASP.NET\r\n";
strHttpRes += "Date: Sat, 24 Oct 2020 02:45:29 GMT\r\n";
strHttpRes += "Content-Length: 30\r\n";
strHttpRes += "\r\n";
strHttpRes += "{\"State\":\"Success\",\"Msg\":\"OK\"}";
http_parser httpParser;
http_parser_settings httpSettings;
// 初使化解析器及回调函数
http_parser_init(&httpParser, HTTP_RESPONSE);
http_parser_settings_init(&httpSettings);
httpSettings.on_message_begin = onMessageBegin;
httpSettings.on_headers_complete = onHeaderComplete;
httpSettings.on_message_complete = onMessageComplete;
httpSettings.on_url = onURL;
httpSettings.on_status = onStatus;
httpSettings.on_header_field = onHeaderField;
httpSettings.on_header_value = onHeaderValue;
httpSettings.on_body = onBody;
// 解析响应
int nParseBytes = http_parser_execute(&httpParser, &httpSettings, strHttpRes.data(), strHttpRes.size());
printf("http_parser_execute => parsebytes:[%d] parseok:[%d] \n", nParseBytes, bParsed);
// 解析成功,打印解析结果
if (bParsed)
{
printf("url: [%s] \n", strUrl.c_str());
printf("status: [%s] \n", strStatus.c_str());
printf("heads: \n");
for (std::map<std::string, std::string>::iterator iter = mapHeadField.begin(); iter != mapHeadField.end(); ++iter)
{
printf("\t %s : %s \n", iter->first.c_str(), iter->second.c_str());
}
printf("body: [%s] \n", strBody.c_str());
}
return 0;
}
int onMessageBegin(http_parser* pParser)
{
printf("@onMessageBegin call \n");
bParsed = false;
return 0;
}
int onHeaderComplete(http_parser* pParser)
{
printf("@onHeaderComplete call \n");
return 0;
}
int onMessageComplete(http_parser* pParser)
{
printf("@onMessageComplete call \n");
bParsed = true;
return 0;
}
int onURL(http_parser* pParser, const char *at, size_t length)
{
printf("@onURL call, length:[%d] \n", length);
strUrl.assign(at, length);
printf("@onURL url:[%s] \n", strUrl.c_str());
return 0;
}
int onStatus(http_parser* pParser, const char *at, size_t length)
{
printf("@onStatus call, length:[%d] \n", length);
strStatus.assign(at, length);
printf("@onStatus status:[%s] \n", strStatus.c_str());
return 0;
}
int onHeaderField(http_parser* pParser, const char *at, size_t length)
{
printf("@onHeaderField call, length:[%d] \n", length);
strFieldTmp.assign(at, length);
printf("@onHeaderField field:[%s] \n", strFieldTmp.c_str());
return 0;
}
int onHeaderValue(http_parser* pParser, const char *at, size_t length)
{
printf("@onHeaderValue call, length:[%d] \n", length);
std::string strValue(at, length);
printf("@onHeaderValue value:[%s] \n", strValue.c_str());
mapHeadField.insert( std::make_pair(strFieldTmp, strValue) );
return 0;
}
int onBody(http_parser* pParser, const char *at, size_t length)
{
printf("@onBody call, length:[%d] \n", length);
printf("@onBody recv:[%s] \n", std::string(at, length).c_str());
strBody.append(at, length);
return 0;
}
执行输出如下:
@onMessageBegin call
@onStatus call, length:[2]
@onStatus status:[OK]
@onHeaderField call, length:[13]
@onHeaderField field:[Cache-Control]
@onHeaderValue call, length:[7]
@onHeaderValue value:[private]
@onHeaderField call, length:[12]
@onHeaderField field:[Content-Type]
@onHeaderValue call, length:[31]
@onHeaderValue value:[application/json; charset=utf-8]
@onHeaderField call, length:[6]
@onHeaderField field:[Server]
@onHeaderValue call, length:[17]
@onHeaderValue value:[Microsoft-IIS/8.0]
@onHeaderField call, length:[19]
@onHeaderField field:[X-AspNetMvc-Version]
@onHeaderValue call, length:[3]
@onHeaderValue value:[5.2]
@onHeaderField call, length:[16]
@onHeaderField field:[X-AspNet-Version]
@onHeaderValue call, length:[9]
@onHeaderValue value:[4.0.30319]
@onHeaderField call, length:[12]
@onHeaderField field:[X-Powered-By]
@onHeaderValue call, length:[7]
@onHeaderValue value:[ASP.NET]
@onHeaderField call, length:[4]
@onHeaderField field:[Date]
@onHeaderValue call, length:[29]
@onHeaderValue value:[Sat, 24 Oct 2020 02:45:29 GMT]
@onHeaderField call, length:[14]
@onHeaderField field:[Content-Length]
@onHeaderValue call, length:[2]
@onHeaderValue value:[30]
@onHeaderComplete call
@onBody call, length:[30]
@onBody recv:[{"State":"Success","Msg":"OK"}]
@onMessageComplete call
http_parser_execute => parsebytes:[282] parseok:[1]
url: []
status: [OK]
heads:
Cache-Control : private
Content-Length : 30
Content-Type : application/json; charset=utf-8
Date : Sat, 24 Oct 2020 02:45:29 GMT
Server : Microsoft-IIS/8.0
X-AspNet-Version : 4.0.30319
X-AspNetMvc-Version : 5.2
X-Powered-By : ASP.NET
body: [{"State":"Success","Msg":"OK"}]