14#include <llhttp/llhttp.h>
25 LOG_TRACE_FMT(
"Received url to parse: {}", std::string_view(url));
27 const auto path_end = url.find(
'?');
28 const auto query_start =
29 path_end == std::string::npos ? url.size() : path_end + 1;
31 const auto query_end = url.find(
'#', query_start);
32 const auto fragment_start =
33 query_end == std::string::npos ? url.size() : query_end + 1;
35 return std::make_tuple(
36 url.substr(0, path_end),
37 url.substr(query_start, query_end - query_start),
38 url.substr(fragment_start));
41 static std::string url_decode(
const std::string_view& s_)
44 char const* src = s.c_str();
45 char const* end = s.c_str() + s.size();
50 char const c = *src++;
51 if (c ==
'%' && (src + 1) < end && isxdigit(src[0]) && isxdigit(src[1]))
53 const auto a = ccf::ds::hex_char_to_int(*src++);
54 const auto b = ccf::ds::hex_char_to_int(*src++);
55 *dst++ = (a << 4) | b;
67 s.resize(dst - s.data());
73 return status >= 200 && status < 300;
91 const std::string_view& url,
93 std::vector<uint8_t>&& body,
115 std::vector<uint8_t>&& body)
override
127 static int on_msg_begin(llhttp_t* parser);
128 static int on_url(llhttp_t* parser,
const char* at,
size_t length);
129 static int on_header_field(llhttp_t* parser,
const char* at,
size_t length);
130 static int on_header_value(llhttp_t* parser,
const char* at,
size_t length);
131 static int on_headers_complete(llhttp_t* parser);
132 static int on_body(llhttp_t* parser,
const char* at,
size_t length);
133 static int on_msg_end(llhttp_t* parser);
150 std::regex url_regex(
151 "^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?");
154 if (!std::regex_match(url, match, url_regex))
156 throw std::invalid_argument(fmt::format(
"Unable to parse url: {}", url));
159 const auto host_port = match[4].str();
163 const auto closing_bracket = host_port.rfind(
']');
164 const auto port_delim_start =
165 closing_bracket == std::string::npos ? 0 : closing_bracket;
166 const auto port_delim = host_port.find(
':', port_delim_start);
169 u.
scheme = match[2].str();
170 u.
host = host_port.substr(0, port_delim);
171 if (port_delim != std::string::npos)
173 u.
port = host_port.substr(port_delim + 1);
175 u.
path = match[5].str();
176 u.
query = match[7].str();
209 settings.on_message_begin = on_msg_begin;
210 settings.on_header_field = on_header_field;
211 settings.on_header_value = on_header_value;
212 settings.on_headers_complete = on_headers_complete;
214 settings.on_message_complete = on_msg_end;
221 void execute(
const uint8_t* data,
size_t size)
223 const auto data_char = (
const char*)data;
224 auto err_no = llhttp_execute(&
parser, data_char, size);
226 if (err_no == HPE_PAUSED_UPGRADE)
230 llhttp_resume_after_upgrade(&
parser);
232 else if (err_no != HPE_OK)
234 throw std::runtime_error(fmt::format(
235 "HTTP parsing failed ({}: {}) around byte {}",
236 llhttp_errno_name(err_no),
237 llhttp_get_error_reason(&
parser),
238 llhttp_get_error_pos(&
parser) - data_char));
247 std::copy(at, at + length, std::back_inserter(
body_buf));
250 ccf::http::default_max_body_size);
251 if (
body_buf.size() > max_body_size)
254 "HTTP request body is too large (max size allowed: {})",
260 throw std::runtime_error(
"Receiving content outside of message");
275 throw std::runtime_error(
276 "Entering new message when previous message isn't complete");
292 throw std::runtime_error(
"Ending message, but not in a message");
304 ccf::http::default_max_headers_count);
305 if (
headers.size() >= max_headers_count)
308 "Too many headers (max number allowed: {})", max_headers_count));
313 auto f = std::string(at, length);
314 ccf::nonstd::to_lower(f);
316 partial_header_key.append(f);
319 ccf::http::default_max_header_size);
320 if (partial_header_key.size() > max_header_size)
323 "Header key for '{}' is too large (max size allowed: {})",
332 partial_header_value.append(at, length);
334 ccf::http::default_max_header_size);
335 if (partial_header_value.size() > max_header_size)
338 "Header value for '{}' is too large (max size allowed: {})",
350 static int on_msg_begin(llhttp_t* parser)
352 Parser* p =
reinterpret_cast<Parser*
>(parser->data);
357 static int on_header_field(llhttp_t* parser,
const char* at,
size_t length)
359 Parser* p =
reinterpret_cast<Parser*
>(parser->data);
360 p->header_field(at, length);
364 static int on_header_value(llhttp_t* parser,
const char* at,
size_t length)
366 Parser* p =
reinterpret_cast<Parser*
>(parser->data);
367 p->header_value(at, length);
371 static int on_headers_complete(llhttp_t* parser)
373 Parser* p =
reinterpret_cast<Parser*
>(parser->data);
374 p->headers_complete();
378 static int on_body(llhttp_t* parser,
const char* at,
size_t length)
380 Parser* p =
reinterpret_cast<Parser*
>(parser->data);
381 p->append_body(at, length);
385 static int on_msg_end(llhttp_t* parser)
387 Parser* p =
reinterpret_cast<Parser*
>(parser->data);
398 std::string url =
"";
405 Parser(HTTP_REQUEST, config),
413 url.append(at, length);
427 llhttp_method(
parser.method),
435 llhttp_method(
parser.method),
443 static int on_url(llhttp_t* parser,
const char* at,
size_t length)
445 RequestParser* p =
reinterpret_cast<RequestParser*
>(parser->data);
446 p->append_url(at, length);
Definition http_parser.h:182
State state
Definition http_parser.h:187
virtual void handle_completed_message()=0
void append_body(const char *at, size_t length)
Definition http_parser.h:242
ccf::http::ParserConfiguration configuration
Definition http_parser.h:186
llhttp_t parser
Definition http_parser.h:184
void headers_complete()
Definition http_parser.h:344
virtual void new_message()
Definition http_parser.h:264
llhttp_settings_t settings
Definition http_parser.h:185
void execute(const uint8_t *data, size_t size)
Definition http_parser.h:221
std::vector< uint8_t > body_buf
Definition http_parser.h:189
void header_value(const char *at, size_t length)
Definition http_parser.h:329
Parser(llhttp_type_t type, const ccf::http::ParserConfiguration &config=ccf::http::ParserConfiguration{})
Definition http_parser.h:201
std::pair< std::string, std::string > partial_parsed_header
Definition http_parser.h:192
void complete_header()
Definition http_parser.h:194
void end_message()
Definition http_parser.h:282
void header_field(const char *at, size_t length)
Definition http_parser.h:296
ccf::http::HeaderMap headers
Definition http_parser.h:190
Definition http_parser.h:394
RequestParser(RequestProcessor &proc_, const ccf::http::ParserConfiguration &config=ccf::http::ParserConfiguration{})
Definition http_parser.h:401
void handle_completed_message() override
Definition http_parser.h:422
void new_message() override
Definition http_parser.h:416
void append_url(const char *at, size_t length)
Definition http_parser.h:411
Definition http_proc.h:20
virtual void handle_request(llhttp_method method, const std::string_view &url, ccf::http::HeaderMap &&headers, std::vector< uint8_t > &&body, int32_t stream_id=http2::DEFAULT_STREAM_ID)=0
Definition http_parser.h:452
ResponseParser(ResponseProcessor &proc_)
Definition http_parser.h:457
void handle_completed_message() override
Definition http_parser.h:462
Definition http_proc.h:31
virtual void handle_response(ccf::http_status status, ccf::http::HeaderMap &&headers, std::vector< uint8_t > &&body)=0
#define LOG_TRACE_FMT
Definition logger.h:356
std::map< std::string, std::string, std::less<> > HeaderMap
Definition http_header_map.h:10
Definition app_interface.h:14
llhttp_status http_status
Definition http_status.h:9
Definition error_reporter.h:6
auto split_url_path(const std::string_view &url)
Definition http_parser.h:23
bool status_success(ccf::http_status status)
Definition http_parser.h:71
State
Definition http_parser.h:122
@ DONE
Definition http_parser.h:123
@ IN_MESSAGE
Definition http_parser.h:124
URL parse_url_full(const std::string &url)
Definition http_parser.h:145
Definition http_configuration.h:24
std::optional< ccf::ds::SizeString > max_header_size
Definition http_configuration.h:26
std::optional< ccf::ds::SizeString > max_body_size
Definition http_configuration.h:25
std::optional< uint32_t > max_headers_count
Definition http_configuration.h:27
Definition http_parser.h:80
std::vector< uint8_t > body
Definition http_parser.h:84
std::string url
Definition http_parser.h:82
ccf::http::HeaderMap headers
Definition http_parser.h:83
llhttp_method method
Definition http_parser.h:81
Definition http_parser.h:77
virtual void handle_request(llhttp_method method, const std::string_view &url, ccf::http::HeaderMap &&headers, std::vector< uint8_t > &&body, int32_t) override
Definition http_parser.h:89
std::queue< Request > received
Definition http_parser.h:87
Definition http_parser.h:104
ccf::http::HeaderMap headers
Definition http_parser.h:106
ccf::http_status status
Definition http_parser.h:105
std::vector< uint8_t > body
Definition http_parser.h:107
Definition http_parser.h:101
std::queue< Response > received
Definition http_parser.h:110
virtual void handle_response(ccf::http_status status, ccf::http::HeaderMap &&headers, std::vector< uint8_t > &&body) override
Definition http_parser.h:112
Definition http_parser.h:136
std::string host
Definition http_parser.h:138
std::string query
Definition http_parser.h:141
std::string port
Definition http_parser.h:139
std::string path
Definition http_parser.h:140
std::string fragment
Definition http_parser.h:142
std::string scheme
Definition http_parser.h:137