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 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
|
// Copyright Maarten L. Hekkelman, Radboud University 2008-2013.
// Copyright Maarten L. Hekkelman, 2014-2026
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#pragma once
/// \file
/// definition of the zeep::http::{request,reply}_parser classes that parse HTTP input/output
#include "zeep/http/header.hpp"
#include "zeep/http/reply.hpp"
#include "zeep/http/request.hpp"
#include <iosfwd>
#include <string>
#include <string_view>
#include <vector>
namespace zeep::http
{
/// An HTTP message parser with support for Transfer-Encoding: Chunked
// --------------------------------------------------------------------
// A simple reimplementation of boost::tribool
class parse_result
{
public:
enum value_type
{
true_value,
false_value,
indeterminate_value
} m_value;
constexpr parse_result() noexcept
: m_value(false_value)
{
}
constexpr parse_result(bool init) noexcept
: m_value(init ? true_value : false_value)
{
}
constexpr parse_result(value_type init) noexcept
: m_value(init)
{
}
constexpr explicit operator bool() const noexcept { return m_value == true_value; }
constexpr bool operator not() const noexcept { return m_value == false_value; }
};
constexpr parse_result::value_type indeterminate = parse_result::indeterminate_value;
constexpr parse_result operator and(parse_result lhs, parse_result rhs)
{
return (static_cast<bool>(not lhs) or static_cast<bool>(not rhs))
? parse_result(false)
: ((static_cast<bool>(lhs) and static_cast<bool>(rhs)) ? parse_result(true) : indeterminate);
}
constexpr parse_result operator and(parse_result lhs, bool rhs)
{
return rhs ? lhs : parse_result(false);
}
constexpr parse_result operator and(bool lhs, parse_result rhs)
{
return lhs ? rhs : parse_result(false);
}
constexpr parse_result operator or(parse_result lhs, parse_result rhs)
{
return (static_cast<bool>(not lhs) and static_cast<bool>(not rhs))
? parse_result(false)
: ((static_cast<bool>(lhs) or static_cast<bool>(rhs)) ? parse_result(true) : indeterminate);
}
constexpr parse_result operator or(parse_result lhs, bool rhs)
{
return rhs ? parse_result(true) : lhs;
}
constexpr parse_result operator or(bool lhs, parse_result rhs)
{
return lhs ? parse_result(true) : rhs;
}
constexpr parse_result operator==(parse_result lhs, parse_result::value_type rhs)
{
return lhs.m_value == rhs;
}
constexpr parse_result operator==(parse_result lhs, parse_result rhs)
{
return (lhs == indeterminate or rhs == indeterminate) ? indeterminate : ((lhs and rhs) or (not lhs and not rhs));
}
// --------------------------------------------------------------------
/// \brief Base class for message parsers.
class parser
{
public:
virtual ~parser() = default;
virtual void reset();
[[nodiscard]] parse_result parse_header_lines(char ch);
[[nodiscard]] parse_result parse_chunk(char ch);
[[nodiscard]] parse_result parse_footer(char ch);
[[nodiscard]] parse_result parse_content(char ch);
protected:
using state_parser = parse_result (parser::*)(char ch);
parser() = default;
parse_result post_process_headers();
[[nodiscard]] bool find_last_token(const header &h, std::string_view t) const;
state_parser m_parser = nullptr;
int m_state = 0;
unsigned int m_chunk_size = 0;
std::string m_data;
std::string m_uri;
std::string m_method;
bool m_parsing_content = false;
bool m_collect_payload = true;
int m_http_version_major = 1, m_http_version_minor = 0;
std::vector<header> m_headers;
std::string m_payload;
};
/// \brief Parser for request messages
class request_parser : public parser
{
public:
request_parser() = default;
parse_result parse(std::streambuf &text);
[[nodiscard]] request get_request();
private:
parse_result parse_initial_line(char ch);
// parse_result post_process_headers() override;
};
/// \brief Parser for reply messages
class reply_parser : public parser
{
public:
reply_parser() = default;
parse_result parse(std::streambuf &text);
[[nodiscard]] reply get_reply();
void reset() override;
private:
parse_result parse_initial_line(char ch);
int m_status = 0;
std::string m_status_line;
};
} // namespace zeep::http
|