Skip to content

Commit 1dc0382

Browse files
committed
http_parser to llhttp, Faster parsing
1 parent 2a581e3 commit 1dc0382

13 files changed

+15775
-85
lines changed

src/network/HttpConnect.cpp

+16-56
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
#include <string_view>
22
#include "HttpConnect.h"
33
#include "BasePacket.h"
4-
#include "http_parser.h"
54
#include "CommonPool.h"
65

76
/*
@@ -25,43 +24,23 @@ Content-Length: 10\r\n\r\n
2524
data......
2625
*/
2726

28-
http_parser_settings http_settings;
2927
HttpConnect::HttpConnect()
3028
{
31-
m_readPacket = new BasePacket();
32-
m_parser = (http_parser *)malloc(sizeof(http_parser));
33-
m_url = (http_parser_url*)malloc(sizeof(http_parser_url));
34-
m_parser->data = this;
35-
36-
http_settings.on_message_begin = NULL;
37-
http_settings.on_url = &HttpConnect::on_url;
38-
http_settings.on_status = NULL;
39-
http_settings.on_header_field = NULL;
40-
http_settings.on_header_value = NULL;
41-
http_settings.on_headers_complete = NULL;
42-
http_settings.on_body = NULL;
43-
http_settings.on_message_complete = NULL;
44-
http_settings.on_chunk_header = NULL;
45-
http_settings.on_chunk_complete = NULL;
46-
47-
http_parser_init(m_parser, HTTP_REQUEST);
48-
29+
m_readPacket = createPacket();
4930
zero();
5031
}
5132

5233
HttpConnect::~HttpConnect()
5334
{
54-
delete m_readPacket;
55-
free(m_parser);
56-
free(m_url);
35+
recyclePacket(m_readPacket);
5736
}
5837

5938
void HttpConnect::zero()
6039
{
6140
TcpSocket::zero();
6241
m_readPacket->zero();
42+
m_parser.zero();
6343
m_residue = 0;
64-
m_urlp = NULL;
6544
m_content = NULL;
6645
}
6746

@@ -105,13 +84,6 @@ const char * HttpConnect::getContentTypeStr(enum http_content_type type)
10584
return ctype;
10685
}
10786

108-
int HttpConnect::on_url(http_parser* _, const char *at, size_t length)
109-
{
110-
HttpConnect * conn = (HttpConnect *)(_->data);
111-
conn->m_urlp = at;
112-
return http_parser_parse_url(at, length, 0, conn->m_url);
113-
}
114-
11587
void HttpConnect::on_msgbuffer(MessageBuffer * buffer)
11688
{
11789
// http head end: \r\n\r\n
@@ -128,18 +100,17 @@ void HttpConnect::on_msgbuffer(MessageBuffer * buffer)
128100
buffer->ReadCompleted(rpos + 4);
129101
m_content = (const char *)(m_readPacket->contents() + m_readPacket->wpos());
130102

131-
if (!parser((const char *)(m_readPacket->contents()), m_readPacket->wpos()))
103+
if (!m_parser.parser((const char *)(m_readPacket->contents()), m_readPacket->wpos()))
132104
{
133105
close();
134106
break;
135107
}
136108
else
137109
{
138-
if (m_parser->method == HTTP_POST)
110+
if (m_parser.method() == HTTP_POST)
139111
{
140-
m_residue = static_cast<int>(m_parser->content_length);
112+
m_residue = static_cast<int>(m_parser.contentLen());
141113
}
142-
m_close = (http_should_keep_alive(m_parser) == 0);
143114
}
144115
}
145116
else
@@ -176,38 +147,27 @@ void HttpConnect::on_msgbuffer(MessageBuffer * buffer)
176147
}
177148
}
178149

179-
bool HttpConnect::parser(const char * buf, int len)
180-
{
181-
http_parser_execute(m_parser, &http_settings, buf, len);
182-
if (m_parser->http_errno != HPE_OK)
183-
{
184-
return false;
185-
}
186-
187-
return true;
188-
}
189-
190150
void HttpConnect::complete()
191151
{
192-
std::string_view path(m_urlp + m_url->field_data[UF_PATH].off, m_url->field_data[UF_PATH].len);
152+
std::string_view path = m_parser.getUrl()->getPath();
193153

194-
if (m_parser->method == HTTP_POST)
154+
if (m_parser.method() == HTTP_POST)
195155
{
196-
std::string_view param(m_content, static_cast<int>(m_parser->content_length));
197-
if (m_event) m_event->onMsg(this, HTTP_POST, path, param);
156+
std::string_view param(m_content, static_cast<int>(m_parser.contentLen()));
157+
if (m_event) m_event->onPost(this, path, param);
198158
}
199-
else if (m_parser->method == HTTP_GET)
159+
else if (m_parser.method() == HTTP_GET)
200160
{
201161
std::string_view param;
202-
if ((m_url->field_set & (1 << UF_QUERY)) != 0)
162+
if (m_parser.getUrl()->haveParam())
203163
{
204-
param = std::string_view(m_urlp + m_url->field_data[UF_QUERY].off, m_url->field_data[UF_QUERY].len);
164+
param = m_parser.getUrl()->getParam();
205165
}
206-
if (m_event) m_event->onMsg(this, HTTP_GET, path, param);
166+
if (m_event) m_event->onGet(this, path, param);
207167
}
208168
else
209169
{
210-
170+
if (m_event) m_event->onOther(this, &m_parser);
211171
}
212172
}
213173

@@ -218,7 +178,7 @@ void HttpConnect::on_clsesocket()
218178

219179
void HttpConnect::on_writecomplete()
220180
{
221-
if (m_close)
181+
if (m_parser.isClose())
222182
{
223183
this->close();
224184
}

src/network/HttpConnect.h

+3-10
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "TcpSocket.h"
1111
#include "HttpEvent.h"
1212
#include "PoolObject.h"
13+
#include "HttpParser.h"
1314

1415
enum http_content_type
1516
{
@@ -25,8 +26,6 @@ enum http_content_type
2526

2627
class BasePacket;
2728
class MessageBuffer;
28-
struct http_parser;
29-
struct http_parser_url;
3029
class HttpConnect : public TcpSocket
3130
{
3231
public:
@@ -46,20 +45,14 @@ class HttpConnect : public TcpSocket
4645
virtual void on_writecomplete();
4746

4847
private:
49-
static int on_url(http_parser*, const char *at, size_t length);
50-
51-
bool parser(const char *, int);
5248
void complete();
5349

5450
private:
5551
HttpEvent * m_event = NULL;
56-
http_parser * m_parser;
57-
http_parser_url * m_url;
5852
BasePacket * m_readPacket;
59-
const char * m_urlp; //url指针
60-
const char * m_content; //post数据指针
53+
HttpParser m_parser;
54+
const char * m_content;
6155
int m_residue;
62-
bool m_close = true;
6356

6457
INCLUDE_POOL_OBJECT
6558
};

src/network/HttpEvent.h

+5-1
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,13 @@
88
************************************************************************/
99

1010
class HttpConnect;
11+
class HttpParser;
1112
class HttpEvent
1213
{
1314
public:
1415
virtual void onClose(HttpConnect *conn) = 0;
15-
virtual void onMsg(HttpConnect *conn, int method, std::string_view & path, std::string_view & data) = 0;
16+
17+
virtual void onGet(HttpConnect* conn, std::string_view& path, std::string_view& data) = 0;
18+
virtual void onPost(HttpConnect* conn, std::string_view& path, std::string_view& data) = 0;
19+
virtual void onOther(HttpConnect* conn, HttpParser * parser) = 0;
1620
};

src/network/HttpServer.cpp

+21-17
Original file line numberDiff line numberDiff line change
@@ -28,30 +28,29 @@ void HttpServer::onClose(HttpConnect *conn)
2828
CommPool::reclaim(conn);
2929
}
3030

31-
void HttpServer::onMsg(HttpConnect *conn, int method, std::string_view & path, std::string_view & data)
31+
void HttpServer::onGet(HttpConnect* conn, std::string_view& path, std::string_view& data)
3232
{
3333
std::string spath(path);
34-
if (method == 1) // get
34+
auto it = m_get.find(spath);
35+
if (it != m_get.end())
3536
{
36-
auto it = m_get.find(spath);
37-
if (it != m_get.end())
38-
{
39-
(it->second)(conn, data);
40-
}
37+
(it->second)(conn, data);
4138
}
42-
else if (method == 3) // post
43-
{
44-
auto it = m_post.find(spath);
45-
if (it != m_post.end())
46-
{
47-
(it->second)(conn, data);
48-
}
49-
}
50-
else
51-
{
39+
}
5240

41+
void HttpServer::onPost(HttpConnect* conn, std::string_view& path, std::string_view& data)
42+
{
43+
std::string spath(path);
44+
auto it = m_post.find(spath);
45+
if (it != m_post.end())
46+
{
47+
(it->second)(conn, data);
5348
}
5449
}
50+
void HttpServer::onOther(HttpConnect* conn, HttpParser* parser)
51+
{
52+
if (m_other) m_other(conn, parser);
53+
}
5554

5655
void HttpServer::addGet(const char * name, std::function<void(HttpConnect *, std::string_view &)> back)
5756
{
@@ -60,4 +59,9 @@ void HttpServer::addGet(const char * name, std::function<void(HttpConnect *, std
6059
void HttpServer::addPost(const char * name, std::function<void(HttpConnect *, std::string_view &)> back)
6160
{
6261
m_post[name] = back;
62+
}
63+
64+
void HttpServer::setOther(std::function<void(HttpConnect*, HttpParser*)> back)
65+
{
66+
m_other = back;
6367
}

src/network/HttpServer.h

+5-1
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,18 @@ class HttpServer : public TcpServer, public HttpEvent
99
HttpServer(EventLoop * loop);
1010
void addGet(const char * name, std::function<void(HttpConnect *, std::string_view &)> back);
1111
void addPost(const char * name, std::function<void(HttpConnect *, std::string_view &)> back);
12+
void setOther(std::function<void(HttpConnect*, HttpParser*)> back);
1213
protected:
1314
virtual TcpSocket * createSocket();
1415
virtual void onSocket(TcpSocket * connect);
1516
virtual void onClose(HttpConnect *conn);
16-
virtual void onMsg(HttpConnect *conn, int method, std::string_view & path, std::string_view & data);
17+
virtual void onGet(HttpConnect* conn, std::string_view& path, std::string_view& data);
18+
virtual void onPost(HttpConnect* conn, std::string_view& path, std::string_view& data);
19+
virtual void onOther(HttpConnect* conn, HttpParser* parser);
1720

1821
private:
1922
std::map<std::string, std::function<void(HttpConnect *, std::string_view &)>> m_get;
2023
std::map<std::string, std::function<void(HttpConnect *, std::string_view &)>> m_post;
24+
std::function<void(HttpConnect*, HttpParser*)> m_other;
2125
};
2226

src/utils/HttpParser.cpp

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
#include "HttpParser.h"
2+
3+
struct HttpSettings : public llhttp_settings_t
4+
{
5+
public:
6+
HttpSettings()
7+
{
8+
llhttp_settings_init(this);
9+
10+
this->on_url = [](llhttp_t* _, const char* at, size_t length)->int {
11+
HttpParser* parser = (HttpParser*)(_->data);
12+
return parser->getUrl()->parse(at, length);
13+
};
14+
}
15+
};
16+
17+
HttpSettings http_settings;
18+
19+
/*static*/ llhttp_settings_t* HttpParser::getSettings()
20+
{
21+
return &http_settings;
22+
}
23+
24+
HttpParser::HttpParser()
25+
{
26+
27+
}
28+
29+
void HttpParser::zero()
30+
{
31+
llhttp_init(&m_parser, HTTP_REQUEST, &http_settings);
32+
m_parser.data = this;
33+
}
34+
#include <stdio.h>
35+
bool HttpParser::parser(const char* buf, int len)
36+
{
37+
enum llhttp_errno err = llhttp_execute(&m_parser, buf, len);
38+
if (err != HPE_OK)
39+
{
40+
fprintf(stderr, "Parse error: %s %s\n", llhttp_errno_name(err), m_parser.reason);
41+
return false;
42+
}
43+
44+
return true;
45+
}

src/utils/HttpParser.h

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#pragma once
2+
3+
#include "llhttp.h"
4+
#include "ParseUrl.h"
5+
6+
class HttpParser
7+
{
8+
public:
9+
HttpParser();
10+
void zero();
11+
12+
static llhttp_settings_t* getSettings();
13+
14+
bool parser(const char* buf, int len);
15+
uint64_t contentLen() { return m_parser.content_length; }
16+
uint8_t method() { return m_parser.method; }
17+
bool isClose() { return llhttp_should_keep_alive(&m_parser) == 0; }
18+
ParseUrl* getUrl() { return &m_url; }
19+
llhttp_t* getParser() { return &m_parser; }
20+
private:
21+
llhttp_t m_parser;
22+
ParseUrl m_url;
23+
};
24+

src/utils/ParseUrl.cpp

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#include "ParseUrl.h"
2+
#include "http_parser.h"
3+
4+
5+
ParseUrl::ParseUrl()
6+
{
7+
m_buff = NULL;
8+
m_url = (struct http_parser_url*)malloc(sizeof(struct http_parser_url));
9+
http_parser_url_init(m_url);
10+
}
11+
12+
ParseUrl::~ParseUrl()
13+
{
14+
if (m_url) {
15+
free(m_url);
16+
m_url = NULL;
17+
}
18+
}
19+
20+
int ParseUrl::parse(const char* buf, int len)
21+
{
22+
m_buff = buf;
23+
return http_parser_parse_url(buf, len, 0, m_url);
24+
}
25+
26+
bool ParseUrl::haveParam()
27+
{
28+
return ((m_url->field_set & (1 << UF_QUERY)) != 0);
29+
}
30+
31+
std::string_view ParseUrl::getPath()
32+
{
33+
return std::string_view(m_buff + m_url->field_data[UF_PATH].off, m_url->field_data[UF_PATH].len);
34+
}
35+
std::string_view ParseUrl::getParam()
36+
{
37+
return std::string_view(m_buff + m_url->field_data[UF_QUERY].off, m_url->field_data[UF_QUERY].len);
38+
}

0 commit comments

Comments
 (0)