File: message-parser.hpp

package info (click to toggle)
libzeep 7.3.2-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,372 kB
  • sloc: cpp: 17,430; javascript: 180; makefile: 12; sh: 11
file content (176 lines) | stat: -rw-r--r-- 4,325 bytes parent folder | download
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