GCC Code Coverage Report


Directory: libs/http_proto/
File: include/boost/http_proto/request.hpp
Date: 2025-10-12 23:51:57
Exec Total Coverage
Lines: 32 32 100.0%
Functions: 10 10 100.0%
Branches: 3 4 75.0%

Line Branch Exec Source
1 //
2 // Copyright (c) 2025 Mohammad Nejati
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_REQUEST_HPP
11 #define BOOST_HTTP_PROTO_REQUEST_HPP
12
13 #include <boost/http_proto/request_base.hpp>
14
15 namespace boost {
16 namespace http_proto {
17
18 /** A modifiable container for HTTP requests.
19
20 This container owns a request, represented by
21 a buffer which is managed by performing
22 dynamic memory allocations as needed. The
23 contents may be inspected and modified, and
24 the implementation maintains a useful
25 invariant: changes to the request always leave
26 it in a valid state.
27
28 @par Example
29 @code
30 request req(method::get, "/");
31
32 req.set(field::host, "example.com");
33 req.set(field::accept_encoding, "gzip, deflate, br");
34 req.set(field::cache_control, "no-cache");
35
36 assert(req.buffer() ==
37 "GET / HTTP/1.1\r\n"
38 "Host: example.com\r\n"
39 "Accept-Encoding: gzip, deflate, br\r\n"
40 "Cache-Control: no-cache\r\n"
41 "\r\n");
42 @endcode
43
44 @see
45 @ref static_request,
46 @ref request_base.
47 */
48 class request
49 : public request_base
50 {
51 public:
52 //--------------------------------------------
53 //
54 // Special Members
55 //
56 //--------------------------------------------
57
58 /** Constructor.
59
60 A default-constructed request contains
61 a valid HTTP `GET` request with no headers.
62
63 @par Example
64 @code
65 request req;
66 @endcode
67
68 @par Postconditions
69 @code
70 this->buffer() == "GET / HTTP/1.1\r\n\r\n"
71 @endcode
72
73 @par Complexity
74 Constant.
75 */
76 64 request() noexcept = default;
77
78 /** Constructor.
79
80 Constructs a request from the string `s`,
81 which must contain valid HTTP request
82 or else an exception is thrown.
83 The new request retains ownership by
84 making a copy of the passed string.
85
86 @par Example
87 @code
88 request req(
89 "GET / HTTP/1.1\r\n"
90 "Accept-Encoding: gzip, deflate, br\r\n"
91 "Cache-Control: no-cache\r\n"
92 "\r\n");
93 @endcode
94
95 @par Postconditions
96 @code
97 this->buffer.data() != s.data()
98 @endcode
99
100 @par Complexity
101 Linear in `s.size()`.
102
103 @par Exception Safety
104 Calls to allocate may throw.
105 Exception thrown on invalid input.
106
107 @throw system_error
108 The input does not contain a valid request.
109
110 @param s The string to parse.
111 */
112 explicit
113 211 request(
114 core::string_view s)
115 211 : request_base(s)
116 {
117 210 }
118
119 /** Constructor.
120
121 The start-line of the request will
122 contain the standard text for the
123 supplied method, target and HTTP version.
124
125 @par Example
126 @code
127 request req(method::get, "/index.html", version::http_1_0);
128 @endcode
129
130 @par Complexity
131 Linear in `to_string(m).size() + t.size()`.
132
133 @par Exception Safety
134 Calls to allocate may throw.
135
136 @param m The method to set.
137
138 @param t The string representing a target.
139
140 @param v The version to set.
141 */
142 request(
143 http_proto::method m,
144 core::string_view t,
145 http_proto::version v) noexcept
146 : request()
147 {
148 set_start_line(m, t, v);
149 }
150
151 /** Constructor.
152
153 The start-line of the request will
154 contain the standard text for the
155 supplied method and target with the HTTP
156 version defaulted to `HTTP/1.1`.
157
158 @par Example
159 @code
160 request req(method::get, "/index.html");
161 @endcode
162
163 @par Complexity
164 Linear in `obsolete_reason(s).size()`.
165
166 @par Exception Safety
167 Calls to allocate may throw.
168
169 @param m The method to set.
170
171 @param t The string representing a target.
172 */
173 request(
174 http_proto::method m,
175 core::string_view t)
176 : request(
177 m, t, http_proto::version::http_1_1)
178 {
179 }
180
181 /** Constructor.
182
183 Allocates `cap` bytes initially, with an
184 upper limit of `max_cap`. Growing beyond
185 `max_cap` will throw an exception.
186
187 Useful when an estimated initial size is
188 known, but further growth up to a maximum
189 is allowed.
190
191 When `cap == max_cap`, the container
192 guarantees to never allocate.
193
194 @par Preconditions
195 @code
196 max_cap >= cap
197 @endcode
198
199 @par Exception Safety
200 Calls to allocate may throw.
201
202 @param cap Initial capacity in bytes (may be `0`).
203
204 @param max_cap Maximum allowed capacity in bytes.
205 */
206 10 request(
207 std::size_t cap,
208 std::size_t max_cap = std::size_t(-1))
209 10 : request()
210 {
211
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 reserve_bytes(cap);
212
2/2
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
10 set_max_capacity_in_bytes(max_cap);
213 10 }
214
215 /** Constructor.
216
217 The contents of `r` are transferred
218 to the newly constructed object,
219 which includes the underlying
220 character buffer.
221 After construction, the moved-from
222 object is as if default-constructed.
223
224 @par Postconditions
225 @code
226 r.buffer() == "GET / HTTP/1.1\r\n\r\n"
227 @endcode
228
229 @par Complexity
230 Constant.
231
232 @param r The request to move from.
233 */
234 26 request(
235 request&& other) noexcept
236 26 : request()
237 {
238 26 swap(other);
239 26 }
240
241 /** Constructor.
242
243 The newly constructed object contains
244 a copy of `r`.
245
246 @par Postconditions
247 @code
248 this->buffer() == r.buffer() && this->buffer.data() != r.buffer().data()
249 @endcode
250
251 @par Complexity
252 Linear in `r.size()`.
253
254 @par Exception Safety
255 Calls to allocate may throw.
256
257 @param r The request to copy.
258 */
259 2 request(
260 request const& r) = default;
261
262 /** Constructor.
263
264 The newly constructed object contains
265 a copy of `r`.
266
267 @par Postconditions
268 @code
269 this->buffer() == r.buffer() && this->buffer.data() != r.buffer().data()
270 @endcode
271
272 @par Complexity
273 Linear in `r.size()`.
274
275 @par Exception Safety
276 Calls to allocate may throw.
277
278 @param r The request to copy.
279 */
280 2 request(
281 request_base const& r)
282 2 : request_base(r)
283 {
284 2 }
285
286 /** Assignment
287
288 The contents of `r` are transferred to
289 `this`, including the underlying
290 character buffer. The previous contents
291 of `this` are destroyed.
292 After assignment, the moved-from
293 object is as if default-constructed.
294
295 @par Postconditions
296 @code
297 r.buffer() == "GET / HTTP/1.1\r\n\r\n"
298 @endcode
299
300 @par Complexity
301 Constant.
302
303 @param r The request to assign from.
304
305 @return A reference to this object.
306 */
307 request&
308 24 operator=(request&& r) noexcept
309 {
310 24 request temp(std::move(r));
311 24 temp.swap(*this);
312 48 return *this;
313 24 }
314
315 /** Assignment.
316
317 The contents of `r` are copied and
318 the previous contents of `this` are
319 discarded.
320
321 @par Postconditions
322 @code
323 this->buffer() == r.buffer() && this->buffer().data() != r.buffer().data()
324 @endcode
325
326 @par Complexity
327 Linear in `r.size()`.
328
329 @par Exception Safety
330 Strong guarantee.
331 Calls to allocate may throw.
332 Exception thrown if max capacity exceeded.
333
334 @throw std::length_error
335 Max capacity would be exceeded.
336
337 @param r The request to copy.
338
339 @return A reference to this object.
340 */
341 request&
342 3 operator=(
343 request const& r)
344 {
345 3 copy_impl(r.h_);
346 3 return *this;
347 }
348
349 /** Assignment.
350
351 The contents of `r` are copied and
352 the previous contents of `this` are
353 discarded.
354
355 @par Postconditions
356 @code
357 this->buffer() == r.buffer() && this->buffer().data() != r.buffer().data()
358 @endcode
359
360 @par Complexity
361 Linear in `r.size()`.
362
363 @par Exception Safety
364 Strong guarantee.
365 Calls to allocate may throw.
366 Exception thrown if max capacity exceeded.
367
368 @throw std::length_error
369 Max capacity would be exceeded.
370
371 @param r The request to copy.
372
373 @return A reference to this object.
374 */
375 request&
376 1 operator=(
377 request_base const& r)
378 {
379 1 copy_impl(r.h_);
380 1 return *this;
381 }
382
383 //--------------------------------------------
384
385 /** Swap.
386
387 Exchanges the contents of this request
388 with another request. All views,
389 iterators and references remain valid.
390
391 If `this == &other`, this function call has no effect.
392
393 @par Example
394 @code
395 request r1(method::get, "/");
396 request r2(method::delete_, "/item/42");
397 r1.swap(r2);
398 assert(r1.buffer() == "DELETE /item/42 HTTP/1.1\r\n\r\n" );
399 assert(r2.buffer() == "GET / HTTP/1.1\r\n\r\n" );
400 @endcode
401
402 @par Complexity
403 Constant
404
405 @param other The object to swap with
406 */
407 void
408 50 swap(request& other) noexcept
409 {
410 50 h_.swap(other.h_);
411 50 std::swap(max_cap_, other.max_cap_);
412 50 }
413
414 /** Swap.
415
416 Exchanges the contents of `v0` with
417 another `v1`. All views, iterators and
418 references remain valid.
419
420 If `&v0 == &v1`, this function call has no effect.
421
422 @par Example
423 @code
424 request r1(method::get, "/");
425 request r2(method::delete_, "/item/42");
426 std::swap(r1, r2);
427 assert(r1.buffer() == "DELETE /item/42 HTTP/1.1\r\n\r\n" );
428 assert(r2.buffer() == "GET / HTTP/1.1\r\n\r\n" );
429 @endcode
430
431 @par Effects
432 @code
433 v0.swap(v1);
434 @endcode
435
436 @par Complexity
437 Constant.
438
439 @param v0 The first object to swap.
440 @param v1 The second object to swap.
441
442 @see
443 @ref request::swap
444 */
445 friend
446 void
447 swap(
448 request& v0,
449 request& v1) noexcept
450 {
451 v0.swap(v1);
452 }
453 };
454
455 } // http_proto
456 } // boost
457
458 #endif
459