Skip to content

Commit f72c592

Browse files
committed
replace head_cb,body_cb,chunked_cb to http_cb
1 parent 89f2b62 commit f72c592

File tree

10 files changed

+122
-105
lines changed

10 files changed

+122
-105
lines changed

README-CN.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -477,7 +477,7 @@ ab -c 100 -n 100000 http://127.0.0.1:8080/
477477

478478
- **libhv QQ群**: `739352073`,欢迎加群交流
479479
- **libhv 源码剖析**: <https://hewei.blog.csdn.net/article/details/123295998>
480-
- **libhv 教程**: <https://hewei.blog.csdn.net/article/details/113733758>
480+
- **libhv 教程目录**: <https://hewei.blog.csdn.net/article/details/113733758>
481481
- [libhv教程01--介绍与体验](https://hewei.blog.csdn.net/article/details/113702536)
482482
- [libhv教程02--编译与安装](https://hewei.blog.csdn.net/article/details/113704737)
483483
- [libhv教程03--链库与使用](https://hewei.blog.csdn.net/article/details/113706378)

examples/curl.cpp

Lines changed: 11 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -263,24 +263,19 @@ int main(int argc, char* argv[]) {
263263
}
264264
}
265265
req.url = url;
266-
267-
HttpResponse res;
268-
/*
269-
res.head_cb = [](const http_headers& headers){
270-
if (verbose) {
271-
for (auto& header : headers) {
272-
fprintf(stderr, "%s: %s\r\n", header.first.c_str(), header.second.c_str());
266+
req.http_cb = [](HttpMessage* res, http_parser_state state, const char* data, size_t size) {
267+
if (state == HP_HEADERS_COMPLETE) {
268+
if (verbose) {
269+
fprintf(stderr, "%s", res->Dump(true, false).c_str());
270+
}
271+
} else if (state == HP_BODY) {
272+
if (data && size) {
273+
printf("%.*s", (int)size, data);
274+
// This program no need to save data to body.
275+
// res->body.append(data, size);
273276
}
274-
fprintf(stderr, "\r\n");
275277
}
276278
};
277-
res.body_cb = [](const char* data, size_t size){
278-
printf("%.*s", (int)size, data);
279-
};
280-
*/
281-
res.chunked_cb = [](const char* data, size_t size){
282-
printf("%.*s", (int)size, data);
283-
};
284279

285280
hv::HttpClient cli;
286281
// http_proxy
@@ -314,6 +309,7 @@ int main(int argc, char* argv[]) {
314309
if (verbose) {
315310
fprintf(stderr, "%s\n", req.Dump(true, true).c_str());
316311
}
312+
HttpResponse res;
317313
ret = cli.send(&req, &res);
318314
if (ret != 0) {
319315
fprintf(stderr, "* Failed:%s:%d\n", http_client_strerror(ret), ret);
@@ -323,11 +319,6 @@ int main(int argc, char* argv[]) {
323319
hv_sleep(retry_delay);
324320
goto send;
325321
}
326-
} else {
327-
if (verbose) {
328-
fprintf(stderr, "%s", res.Dump(true, false).c_str());
329-
}
330-
printf("%s", res.body.c_str());
331322
}
332323
if (--send_count > 0) {
333324
fprintf(stderr, "\nsend again later...%d\n", send_count);

examples/wget.cpp

Lines changed: 69 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,86 +1,101 @@
11
/*
22
* @build: make examples
33
* @server bin/httpd -s restart -d
4-
* @client bin/wget 127.0.0.1:8080/
4+
* @client bin/wget http://127.0.0.1:8080/
55
*/
66

7-
#include "requests.h"
7+
#include "http_client.h"
8+
#include "htime.h"
9+
using namespace hv;
810

9-
static int wget(const char* url, const char* filepath) {
11+
typedef std::function<void(size_t received_bytes, size_t total_bytes)> wget_progress_cb;
12+
13+
static int wget(const char* url, const char* filepath, wget_progress_cb progress_cb = NULL) {
1014
HFile file;
1115
if (file.open(filepath, "wb") != 0) {
1216
fprintf(stderr, "Failed to open file %s\n", filepath);
1317
return -20;
1418
}
1519
printf("Save file to %s ...\n", filepath);
1620

21+
HttpClient cli;
22+
HttpRequest req;
23+
req.url = url;
24+
HttpResponse resp;
25+
1726
// HEAD
18-
auto resp = requests::head(url);
19-
if (resp == NULL) {
20-
fprintf(stderr, "request failed!\n");
27+
req.method = HTTP_HEAD;
28+
int ret = cli.send(&req, &resp);
29+
if (ret != 0) {
30+
fprintf(stderr, "request error: %d\n", ret);
2131
return -1;
2232
}
23-
printd("%s", resp->Dump(true, false).c_str());
24-
if (resp->status_code == HTTP_STATUS_NOT_FOUND) {
33+
printd("%s", resp.Dump(true, false).c_str());
34+
if (resp.status_code == HTTP_STATUS_NOT_FOUND) {
2535
fprintf(stderr, "404 Not Found\n");
2636
return -1;
2737
}
2838

2939
bool use_range = false;
3040
int range_bytes = 1 << 20; // 1M
31-
std::string accept_ranges = resp->GetHeader("Accept-Ranges");
32-
size_t content_length = hv::from_string<size_t>(resp->GetHeader("Content-Length"));
41+
std::string accept_ranges = resp.GetHeader("Accept-Ranges");
42+
size_t content_length = hv::from_string<size_t>(resp.GetHeader("Content-Length"));
3343
// use Range if server accept_ranges and content_length > 1M
34-
if (resp->status_code == 200 &&
44+
if (resp.status_code == 200 &&
3545
accept_ranges == "bytes" &&
3646
content_length > range_bytes) {
3747
use_range = true;
3848
}
3949

4050
// GET
51+
req.method = HTTP_GET;
52+
req.timeout = 3600; // 1h
4153
if (!use_range) {
42-
resp = requests::get(url);
43-
if (resp == NULL) {
44-
fprintf(stderr, "request failed!\n");
54+
size_t received_bytes = 0;
55+
req.http_cb = [&file, &content_length, &received_bytes, &progress_cb]
56+
(HttpMessage* resp, http_parser_state state, const char* data, size_t size) {
57+
if (state == HP_HEADERS_COMPLETE) {
58+
content_length = hv::from_string<size_t>(resp->GetHeader("Content-Length"));
59+
printd("%s", resp->Dump(true, false).c_str());
60+
} else if (state == HP_BODY) {
61+
if (data && size) {
62+
file.write(data, size);
63+
received_bytes += size;
64+
65+
if (progress_cb) {
66+
progress_cb(received_bytes, content_length);
67+
}
68+
}
69+
}
70+
};
71+
ret = cli.send(&req, &resp);
72+
if (ret != 0) {
73+
fprintf(stderr, "request error: %d\n", ret);
4574
return -1;
4675
}
47-
printd("%s", resp->Dump(true, false).c_str());
48-
file.write(resp->body.data(), resp->body.size());
49-
printf("progress: %ld/%ld = 100%%\n", (long)resp->body.size(), (long)resp->body.size());
5076
return 0;
5177
}
5278

5379
// Range: bytes=from-to
5480
long from = 0, to = 0;
55-
int last_progress = 0;
56-
http_client_t* cli = http_client_new();
57-
HttpRequestPtr req(new HttpRequest);
58-
req->method = HTTP_GET;
59-
req->url = url;
6081
while (from < content_length) {
6182
to = from + range_bytes - 1;
6283
if (to >= content_length) to = content_length - 1;
63-
req->SetRange(from, to);
64-
printd("%s", req->Dump(true, false).c_str());
65-
int ret = http_client_send(cli, req.get(), resp.get());
84+
req.SetRange(from, to);
85+
printd("%s", req.Dump(true, false).c_str());
86+
ret = cli.send(&req, &resp);
6687
if (ret != 0) {
67-
fprintf(stderr, "request failed!\n");
88+
fprintf(stderr, "request error: %d\n", ret);
6889
return -1;
6990
}
70-
printd("%s", resp->Dump(true, false).c_str());
71-
file.write(resp->body.data(), resp->body.size());
91+
printd("%s", resp.Dump(true, false).c_str());
92+
file.write(resp.body.data(), resp.body.size());
7293
from = to + 1;
7394

74-
// print progress
75-
int cur_progress = from * 100 / content_length;
76-
if (cur_progress > last_progress) {
77-
printf("\rprogress: %ld/%ld = %d%%", (long)from, (long)content_length, (int)cur_progress);
78-
fflush(stdout);
79-
last_progress = cur_progress;
95+
if (progress_cb) {
96+
progress_cb(from, content_length);
8097
}
8198
}
82-
printf("\n");
83-
http_client_del(cli);
8499

85100
return 0;
86101
}
@@ -101,6 +116,23 @@ int main(int argc, char** argv) {
101116
}
102117
}
103118

104-
wget(url, filepath);
119+
unsigned int start_time = gettick_ms();
120+
int last_progress = 0;
121+
wget(url, filepath, [&last_progress](size_t received_bytes, size_t total_bytes) {
122+
// print progress
123+
if (total_bytes == 0) {
124+
printf("\rprogress: %lu/? = ?", (unsigned long)received_bytes);
125+
} else {
126+
int cur_progress = received_bytes * 100 / total_bytes;
127+
if (cur_progress > last_progress) {
128+
printf("\rprogress: %lu/%lu = %d%%", (unsigned long)received_bytes, (unsigned long)total_bytes, (int)cur_progress);
129+
last_progress = cur_progress;
130+
}
131+
}
132+
fflush(stdout);
133+
});
134+
unsigned int end_time = gettick_ms();
135+
printf("\ncost time %u ms\n", end_time - start_time);
136+
105137
return 0;
106138
}

examples/wrk.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@ typedef struct connection_s {
5757
, ok_cnt(0)
5858
, readbytes(0)
5959
{
60-
response->body_cb = [](const char* data, size_t size) {
61-
// No need to save data
60+
response->http_cb = [](HttpMessage* res, http_parser_state state, const char* data, size_t size) {
61+
// wrk no need to save data to body
6262
};
6363
}
6464

http/Http1Parser.cpp

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,7 @@ int on_body(http_parser* parser, const char *at, size_t length) {
7575
// printd("on_body:%.*s\n", (int)length, at);
7676
Http1Parser* hp = (Http1Parser*)parser->data;
7777
hp->state = HP_BODY;
78-
if (hp->parsed->body_cb) {
79-
hp->parsed->body_cb(at, length);
80-
} else {
78+
if (hp->invokeHttpCb(at, length) != 0) {
8179
hp->parsed->body.append(at, length);
8280
}
8381
return 0;
@@ -87,6 +85,7 @@ int on_message_begin(http_parser* parser) {
8785
printd("on_message_begin\n");
8886
Http1Parser* hp = (Http1Parser*)parser->data;
8987
hp->state = HP_MESSAGE_BEGIN;
88+
hp->invokeHttpCb();
9089
return 0;
9190
}
9291

@@ -126,38 +125,35 @@ int on_headers_complete(http_parser* parser) {
126125
}
127126
}
128127
hp->state = HP_HEADERS_COMPLETE;
129-
if (hp->parsed->head_cb) {
130-
hp->parsed->head_cb(hp->parsed->headers);
131-
}
128+
hp->invokeHttpCb();
132129
return skip_body ? 1 : 0;
133130
}
134131

135132
int on_message_complete(http_parser* parser) {
136133
printd("on_message_complete\n");
137134
Http1Parser* hp = (Http1Parser*)parser->data;
138135
hp->state = HP_MESSAGE_COMPLETE;
136+
hp->invokeHttpCb();
139137
return 0;
140138
}
141139

142140
int on_chunk_header(http_parser* parser) {
143141
printd("on_chunk_header:%llu\n", parser->content_length);
144142
Http1Parser* hp = (Http1Parser*)parser->data;
145-
hp->state = HP_CHUNK_HEADER;
146143
int chunk_size = parser->content_length;
147144
int reserve_size = MIN(chunk_size + 1, MAX_CONTENT_LENGTH);
148145
if (reserve_size > hp->parsed->body.capacity()) {
149146
hp->parsed->body.reserve(reserve_size);
150147
}
148+
hp->state = HP_CHUNK_HEADER;
149+
hp->invokeHttpCb(NULL, chunk_size);
151150
return 0;
152151
}
153152

154153
int on_chunk_complete(http_parser* parser) {
155154
printd("on_chunk_complete\n");
156155
Http1Parser* hp = (Http1Parser*)parser->data;
157156
hp->state = HP_CHUNK_COMPLETE;
158-
if (hp->parsed->chunked_cb) {
159-
hp->parsed->chunked_cb(hp->parsed->body.c_str(), hp->parsed->body.size());
160-
hp->parsed->body.clear();
161-
}
157+
hp->invokeHttpCb();
162158
return 0;
163159
}

http/Http1Parser.h

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,6 @@
44
#include "HttpParser.h"
55
#include "http_parser.h"
66

7-
enum http_parser_state {
8-
HP_START_REQ_OR_RES,
9-
HP_MESSAGE_BEGIN,
10-
HP_URL,
11-
HP_STATUS,
12-
HP_HEADER_FIELD,
13-
HP_HEADER_VALUE,
14-
HP_HEADERS_COMPLETE,
15-
HP_CHUNK_HEADER,
16-
HP_BODY,
17-
HP_CHUNK_COMPLETE,
18-
HP_MESSAGE_COMPLETE
19-
};
20-
217
class Http1Parser : public HttpParser {
228
public:
239
static http_parser_settings cbs;
@@ -132,6 +118,13 @@ class Http1Parser : public HttpParser {
132118
submited = res;
133119
return 0;
134120
}
121+
122+
// HttpMessage::http_cb
123+
int invokeHttpCb(const char* data = NULL, size_t size = 0) {
124+
if (parsed->http_cb == NULL) return -1;
125+
parsed->http_cb(parsed, state, data, size);
126+
return 0;
127+
}
135128
};
136129

137130
#endif // HV_HTTP1_PARSER_H_

http/HttpMessage.h

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -88,10 +88,6 @@ typedef std::map<std::string, std::string, hv::StringCaseLess> http_headers;
8888
typedef std::vector<HttpCookie> http_cookies;
8989
typedef std::string http_body;
9090

91-
typedef std::function<void(const http_headers& headers)> http_head_cb;
92-
typedef std::function<void(const char* data, size_t size)> http_body_cb;
93-
typedef std::function<void(const char* data, size_t size)> http_chunked_cb;
94-
9591
HV_EXPORT extern http_headers DefaultHeaders;
9692
HV_EXPORT extern http_body NoBody;
9793

@@ -106,9 +102,8 @@ class HV_EXPORT HttpMessage {
106102
http_cookies cookies;
107103
http_body body;
108104

109-
http_head_cb head_cb;
110-
http_body_cb body_cb;
111-
http_chunked_cb chunked_cb; // Transfer-Encoding: chunked
105+
// http_cb
106+
std::function<void(HttpMessage*, http_parser_state state, const char* data, size_t size)> http_cb;
112107

113108
// structured content
114109
void* content; // DATA_NO_COPY

http/client/AsyncHttpClient.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -144,9 +144,7 @@ int AsyncHttpClient::sendRequest(const SocketChannelPtr& channel) {
144144
resp = new HttpResponse;
145145
ctx->resp.reset(resp);
146146
}
147-
if (req->head_cb) resp->head_cb = std::move(req->head_cb);
148-
if (req->body_cb) resp->body_cb = std::move(req->body_cb);
149-
if (req->chunked_cb) resp->chunked_cb = std::move(req->chunked_cb);
147+
if (req->http_cb) resp->http_cb = std::move(req->http_cb);
150148

151149
ctx->parser->InitResponse(resp);
152150
ctx->parser->SubmitRequest(req);

0 commit comments

Comments
 (0)