-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathhttp_request.cpp
More file actions
159 lines (126 loc) · 3.83 KB
/
http_request.cpp
File metadata and controls
159 lines (126 loc) · 3.83 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
#include "http_request.h"
#include <bits/stdc++.h>
using namespace std;
http_request::http_request(const string &s) {
http_parser_init(&m_parse, HTTP_REQUEST);
m_settings = {
.on_message_begin = 0
,.on_url = on_url_cb
,.on_status = 0
,.on_header_field = on_header_field_cb
,.on_header_value = on_header_value_cb
,.on_headers_complete = on_headers_complete_cb
,.on_body = on_body_cb
,.on_message_complete = on_message_complete_cb
,.on_chunk_header = 0
,.on_chunk_complete = 0
};
m_is_multipart = false;
m_parse.data = this;
m_data = const_cast<char*>(s.c_str());
m_len = s.size();
http_parser_execute(&m_parse, &m_settings, m_data, m_len);
}
void http_request::set_latest_field(std::string latest_field) {
m_latest_field = latest_field;
}
void http_request::set_header(const std::string &value) {
m_headers[m_latest_field] = value;
if (m_latest_field == "Content-Type" && value.find("multipart/form-data") != string::npos) {
m_is_multipart = true;
auto boundary_pos = value.find("boundary=");
boundary_pos += strlen("boundary=");
m_multipart_boundary = value.substr(boundary_pos);
}
}
void http_request::set_url(std::string url) {
m_url = url;
if (auto pos = url.find("?"); pos != string::npos) {
m_path = url.substr(0, pos);
m_query_string = url.substr(pos + 1);
} else {
m_path = url;
}
}
void http_request::set_method(std::string method) {
m_method = method;
}
void http_request::append_body(std::string body_part) {
m_body_buf += body_part;
}
void http_request::set_request_status(request_status status) {
m_request_status = status;
if (m_is_multipart) {
size_t pos = 0;
while (pos < m_body_buf.size()) {
auto nxt = m_body_buf.find("--" + m_multipart_boundary, pos);
if (nxt == string::npos) {
break;
}
if (nxt != pos && m_multipart_data.size() > 0) {
m_multipart_data.back() += m_body_buf.substr(pos, nxt - pos);
}
m_multipart_data.push_back("");
pos = nxt + 2 + m_multipart_boundary.size();
}
m_multipart_data.pop_back();
}
}
std::map<std::string, std::string> http_request::get_headers() {
return m_headers;
}
std::string http_request::get_url() {
return m_url;
}
std::string http_request::get_method() {
return m_method;
}
std::string http_request::get_body() {
return m_body_buf;
}
std::string http_request::get_path() {
return m_path;
}
std::string http_request::get_query_string() {
return m_query_string;
}
const vector<std::string>& http_request::get_multipart_data() {
return m_multipart_data;
}
bool http_request::is_valid() {
return m_request_status == REQUEST_VALID;
}
bool http_request::is_multipart() {
return m_is_multipart;
}
int http_request::on_header_field_cb(http_parser *parser, const char *buf, size_t len) {
self_type *impl = reinterpret_cast<self_type*>(parser->data);
impl->set_latest_field(std::string(buf, len));
return 0;
}
int http_request::on_header_value_cb(http_parser *parser, const char *buf, size_t len) {
self_type *impl = reinterpret_cast<self_type*>(parser->data);
impl->set_header(std::string(buf, len));
return 0;
}
int http_request::on_url_cb(http_parser *parser, const char *buf, size_t len) {
self_type *impl = reinterpret_cast<self_type*>(parser->data);
impl->set_url(std::string(buf, len));
return 0;
}
int http_request::on_headers_complete_cb(http_parser *parser) {
self_type *impl = reinterpret_cast<self_type*>(parser->data);
std::string method = http_method_str((http_method)parser->method);
impl->set_method(method);
return 0;
}
int http_request::on_body_cb(http_parser *parser, const char *buf, size_t len) {
self_type *impl = reinterpret_cast<self_type*>(parser->data);
impl->append_body(std::string(buf, len));
return 0;
}
int http_request::on_message_complete_cb(http_parser *parser) {
self_type *impl = reinterpret_cast<self_type*>(parser->data);
impl->set_request_status(REQUEST_VALID);
return 0;
}