GCC Code Coverage Report


Directory: libs/http_proto/include/boost/http_proto/
File: boost/http_proto/parser.hpp
Date: 2023-01-26 23:44:13
Exec Total Coverage
Lines: 6 7 85.7%
Functions: 4 5 80.0%
Branches: 0 2 0.0%

Line Branch Exec Source
1 //
2 // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // Official repository: https://github.com/CPPAlliance/http_proto
8 //
9
10 #ifndef BOOST_HTTP_PROTO_BASIC_PARSER_HPP
11 #define BOOST_HTTP_PROTO_BASIC_PARSER_HPP
12
13 #include <boost/http_proto/detail/config.hpp>
14 #include <boost/http_proto/buffer.hpp>
15 #include <boost/http_proto/error.hpp>
16 #include <boost/http_proto/sink.hpp>
17 #include <boost/http_proto/string_view.hpp>
18 #include <boost/http_proto/detail/circular_buffer.hpp>
19 #include <boost/http_proto/detail/flat_buffer.hpp>
20 #include <boost/http_proto/detail/header.hpp>
21 #include <boost/http_proto/detail/workspace.hpp>
22 #include <boost/url/grammar/error.hpp>
23 #include <boost/optional.hpp>
24 #include <cstddef>
25 #include <cstdint>
26 #include <memory>
27 #include <utility>
28
29 namespace boost {
30 namespace http_proto {
31
32 #ifndef BOOST_HTTP_PROTO_DOCS
33 enum class version : char;
34 class request_parser;
35 class response_parser;
36 struct brotli_decoder_t;
37 struct brotli_encoder_t;
38 struct deflate_decoder_t;
39 struct deflate_encoder_t;
40 struct gzip_decoder_t;
41 struct gzip_encoder_t;
42 namespace detail {
43 struct codec;
44 }
45 #endif
46
47 /** A parser for HTTP/1 messages.
48
49 The parser is strict. Any malformed
50 inputs according to the documented
51 HTTP ABNFs is treated as an
52 unrecoverable error.
53 */
54 class BOOST_SYMBOL_VISIBLE
55 parser
56 {
57 public:
58 /** Parser configuration settings
59
60 @see
61 @li <a href="https://stackoverflow.com/questions/686217/maximum-on-http-header-values"
62 >Maximum on HTTP header values (Stackoverflow)</a>
63 */
64 struct config_base
65 {
66 /** Largest allowed size for the headers.
67
68 This determines an upper bound on the
69 allowed size of the start-line plus
70 all of the individual fields in the
71 headers. This counts all delimiters
72 including trailing CRLFs.
73 */
74 std::size_t headers_limit = 16 * 1024;
75
76 /** Largest allowed size for the start-line.
77
78 This determines an upper bound on the
79 allowed size for the request-line of
80 an HTTP request or the status-line of
81 an HTTP response.
82 */
83 std::size_t start_line_limit = 4096;
84
85 /** Largest size for one field.
86
87 This determines an upper bound on the
88 allowed size for any single header
89 in an HTTP message. This counts
90 the field name, field value, and
91 delimiters including a trailing CRLF.
92 */
93 std::size_t field_size_limit = 4096;
94
95 /** Largest allowed number of fields.
96
97 This determines an upper bound on the
98 largest number of individual header
99 fields that may appear in an HTTP
100 message.
101 */
102 std::size_t fields_limit = 100;
103
104 /** Largest allowed size for a content body.
105
106 The size of the body is measured
107 after removing any transfer encodings,
108 including a chunked encoding.
109 */
110 std::uint64_t body_limit = 64 * 1024;
111 };
112
113 using buffers = mutable_buffers_pair;
114
115 private:
116 BOOST_HTTP_PROTO_DECL parser(
117 detail::kind, config_base const&);
118 BOOST_HTTP_PROTO_DECL void construct(
119 std::size_t extra_buffer_size);
120 public:
121
122 //--------------------------------------------
123 //
124 // Special Members
125 //
126 //--------------------------------------------
127
128 /** Destructor
129 */
130 BOOST_HTTP_PROTO_DECL
131 ~parser();
132
133 /** Constructor
134 */
135 BOOST_HTTP_PROTO_DECL
136 parser(parser&&) noexcept;
137
138 //--------------------------------------------
139 //
140 // Observers
141 //
142 //--------------------------------------------
143
144 #if 0
145 /** Return true if any input was committed.
146 */
147 bool
148 got_some() const noexcept
149 {
150 return st_ != state::need_start;
151 }
152 #endif
153
154 /** Return true if the complete header was parsed.
155 */
156 bool
157 got_header() const noexcept
158 {
159 return st_ > state::headers;
160 }
161
162 /** Returns `true` if a complete message has been parsed.
163
164 Calling @ref reset prepares the parser
165 to process the next message in the stream.
166
167 */
168 bool
169 is_complete() const noexcept
170 {
171 return st_ == state::complete;
172 }
173
174 BOOST_HTTP_PROTO_DECL
175 string_view
176 body() const noexcept;
177
178 //--------------------------------------------
179 //
180 // Modifiers
181 //
182 //--------------------------------------------
183
184 /** Prepare for a new stream.
185 */
186 BOOST_HTTP_PROTO_DECL
187 void
188 reset() noexcept;
189
190 private:
191 // New message on the current stream
192 BOOST_HTTP_PROTO_DECL void
193 start_impl(bool head_response);
194 public:
195
196 /** Return the input buffer
197 */
198 BOOST_HTTP_PROTO_DECL
199 buffers
200 prepare();
201
202 /** Commit bytes to the input buffer
203 */
204 BOOST_HTTP_PROTO_DECL
205 void
206 commit(
207 std::size_t n);
208
209 /** Indicate there will be no more input
210 */
211 BOOST_HTTP_PROTO_DECL
212 void
213 commit_eof();
214
215 /** Parse pending input data
216 */
217 BOOST_HTTP_PROTO_DECL
218 void
219 parse(
220 error_code& ec);
221
222 //--------------------------------------------
223
224 /** Return any leftover data
225
226 This is used to forward unconsumed data
227 that could lie past the last message.
228 For example on a CONNECT request there
229 could be additional protocol-dependent
230 data that we want to retrieve.
231 */
232 BOOST_HTTP_PROTO_DECL
233 string_view
234 release_buffered_data() noexcept;
235
236 private:
237 744 void apply_params() noexcept
238 {
239 744 }
240
241 void apply_param(...) = delete;
242
243 template<class P0, class... Pn>
244 void
245 8 apply_params(P0&& p0, Pn&&... pn)
246 {
247 // If you get an error here it means
248 // you passed an unknown parameter type.
249 8 apply_param(std::forward<P0>(p0));
250
251 8 apply_params(std::forward<Pn>(pn)...);
252 8 }
253
254 BOOST_HTTP_PROTO_DECL void apply_param(config_base const&) noexcept;
255
256 // in detail/impl/brotli_codec.ipp
257 BOOST_HTTP_PROTO_EXT_DECL void apply_param(brotli_decoder_t const&);
258
259 // in detail/impl/zlib_codec.ipp
260 BOOST_HTTP_PROTO_ZLIB_DECL void apply_param(deflate_decoder_t const&);
261 BOOST_HTTP_PROTO_ZLIB_DECL void apply_param(gzip_decoder_t const&);
262
263 detail::header const* safe_get_header() const;
264 void parse_body(error_code&);
265 void parse_chunk(error_code&);
266
267 friend class request_parser;
268 friend class response_parser;
269
270 enum
271 {
272 br_codec = 0,
273 deflate_codec = 1,
274 gzip_codec = 2
275 };
276
277 enum class state
278 {
279 // order matters
280 need_start,
281 headers, // header fields
282 headers_done, // delivered headers
283 body, // reading payload
284 complete, // done
285 };
286
287 config_base cfg_;
288 detail::header h_;
289 detail::workspace ws_;
290 detail::header::config cfg_impl_;
291
292 std::unique_ptr<
293 detail::codec> dec_[3];
294 detail::flat_buffer h_buf_;
295 detail::circular_buffer b_buf_;
296 detail::circular_buffer c_buf_;
297 detail::codec* cod_;
298
299 state st_;
300 bool got_eof_;
301 bool head_response_;
302 };
303
304 } // http_proto
305 } // boost
306
307 #include <boost/http_proto/impl/parser.hpp>
308
309 #endif
310