26 #ifndef STATICLIB_PION_HTTP_MESSAGE_HPP
27 #define STATICLIB_PION_HTTP_MESSAGE_HPP
34 #include <unordered_map>
39 #include "staticlib/config.hpp"
40 #include "staticlib/utils.hpp"
102 virtual const char*
name() const STATICLIB_NOEXCEPT {
103 return "receive_error_t";
116 result =
"HTTP message parsing error";
119 result =
"Unknown receive error";
215 std::unique_ptr<char[]> m_buf;
244 memcpy(
get(), buf.
get(), buf.
size());
254 memcpy(
get(), buf.
get(), buf.
size());
278 const char *
get()
const {
298 m_buf.reset(
new char[len + 1]);
299 memset(m_buf.get(),
'\0', len + 1);
317 using headers_type = std::unordered_multimap<std::string, std::string, algorithm::ihash, algorithm::iequal_to>;
332 bool m_chunks_supported;
337 bool m_do_not_send_content_length;
342 asio::ip::address m_remote_ip;
347 uint16_t m_version_major;
352 uint16_t m_version_minor;
357 size_t m_content_length;
362 content_buffer_t m_content_buf;
367 std::vector<char> m_chunk_cache;
372 headers_type m_headers;
377 headers_type m_cookie_params;
387 bool m_has_missing_packets;
392 bool m_has_data_after_missing;
402 m_chunks_supported(false),
403 m_do_not_send_content_length(false),
409 m_has_missing_packets(false),
410 m_has_data_after_missing(false) { }
417 m_is_valid(http_msg.m_is_valid),
418 m_is_chunked(http_msg.m_is_chunked),
419 m_chunks_supported(http_msg.m_chunks_supported),
420 m_do_not_send_content_length(http_msg.m_do_not_send_content_length),
421 m_remote_ip(http_msg.m_remote_ip),
422 m_version_major(http_msg.m_version_major),
423 m_version_minor(http_msg.m_version_minor),
424 m_content_length(http_msg.m_content_length),
425 m_content_buf(http_msg.m_content_buf),
426 m_chunk_cache(http_msg.m_chunk_cache),
427 m_headers(http_msg.m_headers),
428 m_status(http_msg.m_status),
429 m_has_missing_packets(http_msg.m_has_missing_packets),
430 m_has_data_after_missing(http_msg.m_has_data_after_missing) { }
440 m_is_valid = http_msg.m_is_valid;
441 m_is_chunked = http_msg.m_is_chunked;
442 m_chunks_supported = http_msg.m_chunks_supported;
443 m_do_not_send_content_length = http_msg.m_do_not_send_content_length;
444 m_remote_ip = http_msg.m_remote_ip;
445 m_version_major = http_msg.m_version_major;
446 m_version_minor = http_msg.m_version_minor;
447 m_content_length = http_msg.m_content_length;
448 m_content_buf = http_msg.m_content_buf;
449 m_chunk_cache = http_msg.m_chunk_cache;
450 m_headers = http_msg.m_headers;
451 m_status = http_msg.m_status;
452 m_has_missing_packets = http_msg.m_has_missing_packets;
453 m_has_data_after_missing = http_msg.m_has_data_after_missing;
467 m_is_valid = m_is_chunked = m_chunks_supported
468 = m_do_not_send_content_length =
false;
469 m_remote_ip = asio::ip::address_v4(0);
470 m_version_major = m_version_minor = 1;
471 m_content_length = 0;
472 m_content_buf.
clear();
473 m_chunk_cache.clear();
475 m_cookie_params.clear();
477 m_has_missing_packets =
false;
478 m_has_data_after_missing =
false;
499 return m_chunks_supported;
515 return m_version_major;
522 return m_version_minor;
542 return m_content_length;
565 return m_content_buf.
size();
572 return m_content_buf.
get();
581 return m_content_buf.
get();
588 return m_chunk_cache;
594 const std::string&
get_header(
const std::string& key)
const {
599 auto range = m_headers.equal_range(key);
600 for (
auto it = range.first; it != range.second; ++it) {
601 if (std::string::npos == it->second.find(
',')) {
602 if (sl::utils::iequals(value, it->second)) {
606 auto vec = sl::utils::split(it->second,
',');
607 for (
auto& el : vec) {
608 auto trimmed = sl::utils::trim(el);
609 if (sl::utils::iequals(value, trimmed)) {
634 return (m_headers.find(key) != m_headers.end());
644 const std::string&
get_cookie(
const std::string& key)
const {
654 return m_cookie_params;
665 return (m_cookie_params.find(key) != m_cookie_params.end());
675 void add_cookie(
const std::string& key,
const std::string& value) {
676 m_cookie_params.insert(std::make_pair(key, value));
718 return m_has_missing_packets;
727 m_has_missing_packets = newVal;
736 return m_has_data_after_missing;
745 m_has_data_after_missing = newVal;
763 m_chunks_supported = b;
801 m_content_length = n;
808 m_do_not_send_content_length =
true;
834 if (i == m_headers.end()) {
835 m_content_length = 0;
837 std::string trimmed_length(i->second);
838 sl::utils::trim(trimmed_length);
839 m_content_length =
static_cast<size_t>(sl::utils::parse_uint64(trimmed_length));
847 m_is_chunked =
false;
849 if (i != m_headers.end()) {
852 if (std::string::npos != i->second.find(
"chunked") ||
853 std::string::npos != i->second.find(
"Chunked")) {
856 m_is_chunked =
false;
869 m_content_buf.
resize(m_content_length);
870 return m_content_buf.
get();
881 memcpy(m_content_buf.
get(), content.c_str(), content.size());
908 void add_header(
const std::string& key,
const std::string& value) {
909 m_headers.insert(std::make_pair(key, value));
950 const bool using_chunks) {
955 write_buffers.push_back(asio::buffer(
STRING_CRLF));
968 if (m_chunk_cache.size() > 0) {
969 std::memcpy(post_buffer, m_chunk_cache.data(), m_chunk_cache.size());
983 std::string query_string;
984 for (headers_type::const_iterator i = query_params.begin();
985 i != query_params.end(); ++i) {
986 if (i != query_params.begin()) {
989 query_string += sl::utils::url_encode(i->first);
991 query_string += sl::utils::url_encode(i->second);
1008 const std::string& path,
const bool has_max_age =
false,
const unsigned long max_age = 0) {
1010 std::string set_cookie_header(name);
1011 set_cookie_header +=
"=\"";
1012 set_cookie_header += value;
1013 set_cookie_header +=
"\"; Version=1";
1014 if (!path.empty()) {
1015 set_cookie_header +=
"; Path=";
1016 set_cookie_header += path;
1019 set_cookie_header +=
"; Max-Age=";
1020 set_cookie_header += sl::support::to_string(max_age);
1022 return set_cookie_header;
1037 }
else if (!m_do_not_send_content_length) {
1049 for (headers_type::const_iterator i = m_headers.begin(); i != m_headers.end(); ++i) {
1050 write_buffers.push_back(asio::buffer(i->first));
1052 write_buffers.push_back(asio::buffer(i->second));
1053 write_buffers.push_back(asio::buffer(
STRING_CRLF));
1056 write_buffers.push_back(asio::buffer(
STRING_CRLF));
1072 static const std::string&
get_value(
const headers_type& dict,
const std::string& key) {
1073 auto i = dict.find(key);
1086 inline static void change_value(headers_type& dict,
const std::string& key,
1087 const std::string& value) {
1089 auto result_pair = dict.equal_range(key);
1090 if (result_pair.first == dict.end()) {
1092 dict.insert(std::make_pair(key, value));
1095 result_pair.first->second = value;
1097 headers_type::iterator i;
1098 ++(result_pair.first);
1099 while (result_pair.first != result_pair.second) {
1100 i = result_pair.first;
1101 ++(result_pair.first);
1113 inline static void delete_value(headers_type& dict,
const std::string& key) {
1114 auto result_pair = dict.equal_range(key);
1115 if (result_pair.first != dict.end()) {
1116 dict.erase(result_pair.first, result_pair.second);
1141 #endif // STATICLIB_PION_HTTP_MESSAGE_HPP