GCC Code Coverage Report


Directory: ./
File: libs/http_proto/include/boost/http_proto/request.hpp
Date: 2025-12-18 06:34:37
Exec Total Coverage
Lines: 58 58 100.0%
Functions: 17 17 100.0%
Branches: 2 2 100.0%

Line Branch Exec Source
1 //
2 // Copyright (c) 2021 Vinnie Falco (vinnie.falco@gmail.com)
3 // Copyright (c) 2025 Mohammad Nejati
4 //
5 // Distributed under the Boost Software License, Version 1.0. (See accompanying
6 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 //
8 // Official repository: https://github.com/cppalliance/http_proto
9 //
10
11 #ifndef BOOST_HTTP_PROTO_REQUEST_HPP
12 #define BOOST_HTTP_PROTO_REQUEST_HPP
13
14 #include <boost/http_proto/detail/config.hpp>
15 #include <boost/http_proto/message_base.hpp>
16
17 namespace boost {
18 namespace http_proto {
19
20 /** A container for HTTP requests.
21
22 This container owns a request, represented by
23 a buffer which is managed by performing
24 dynamic memory allocations as needed. The
25 contents may be inspected and modified, and
26 the implementation maintains a useful
27 invariant: changes to the request always leave
28 it in a valid state.
29
30 @par Example
31 @code
32 request req(method::get, "/");
33
34 req.set(field::host, "example.com");
35 req.set(field::accept_encoding, "gzip, deflate, br");
36 req.set(field::cache_control, "no-cache");
37
38 assert(req.buffer() ==
39 "GET / HTTP/1.1\r\n"
40 "Host: example.com\r\n"
41 "Accept-Encoding: gzip, deflate, br\r\n"
42 "Cache-Control: no-cache\r\n"
43 "\r\n");
44 @endcode
45
46 @see
47 @ref request_parser,
48 @ref response.
49 */
50 class request
51 : public message_base
52 {
53 friend class request_parser;
54
55 315 request(
56 view_tag_t,
57 detail::header const& h) noexcept
58 315 : message_base(view_tag, h)
59 {
60 315 }
61
62 public:
63 //--------------------------------------------
64 //
65 // Special Members
66 //
67 //--------------------------------------------
68
69 /** Constructor.
70
71 A default-constructed request contains
72 a valid HTTP `GET` request with no headers.
73
74 @par Example
75 @code
76 request req;
77 @endcode
78
79 @par Postconditions
80 @code
81 this->buffer() == "GET / HTTP/1.1\r\n\r\n"
82 @endcode
83
84 @par Complexity
85 Constant.
86 */
87 28 request() noexcept
88 28 : message_base(detail::kind::request)
89 {
90 28 }
91
92 /** Constructor.
93
94 Constructs a request from the string `s`,
95 which must contain valid HTTP request
96 or else an exception is thrown.
97 The new request retains ownership by
98 making a copy of the passed string.
99
100 @par Example
101 @code
102 request req(
103 "GET / HTTP/1.1\r\n"
104 "Accept-Encoding: gzip, deflate, br\r\n"
105 "Cache-Control: no-cache\r\n"
106 "\r\n");
107 @endcode
108
109 @par Postconditions
110 @code
111 this->buffer.data() != s.data()
112 @endcode
113
114 @par Complexity
115 Linear in `s.size()`.
116
117 @par Exception Safety
118 Calls to allocate may throw.
119 Exception thrown on invalid input.
120
121 @throw system_error
122 The input does not contain a valid request.
123
124 @param s The string to parse.
125 */
126 explicit
127 208 request(
128 core::string_view s)
129 208 : message_base(detail::kind::request, s)
130 {
131 207 }
132
133 /** Constructor.
134
135 The start-line of the request will
136 contain the standard text for the
137 supplied method, target and HTTP version.
138
139 @par Example
140 @code
141 request req(method::get, "/index.html", version::http_1_0);
142 @endcode
143
144 @par Complexity
145 Linear in `to_string(m).size() + t.size()`.
146
147 @par Exception Safety
148 Calls to allocate may throw.
149
150 @param m The method to set.
151
152 @param t The string representing a target.
153
154 @param v The version to set.
155 */
156 request(
157 http_proto::method m,
158 core::string_view t,
159 http_proto::version v) noexcept
160 : message_base(detail::kind::request)
161 {
162 set_start_line(m, t, v);
163 }
164
165 /** Constructor.
166
167 The start-line of the request will
168 contain the standard text for the
169 supplied method and target with the HTTP
170 version defaulted to `HTTP/1.1`.
171
172 @par Example
173 @code
174 request req(method::get, "/index.html");
175 @endcode
176
177 @par Complexity
178 Linear in `to_string(s).size()`.
179
180 @par Exception Safety
181 Calls to allocate may throw.
182
183 @param m The method to set.
184
185 @param t The string representing a target.
186 */
187 request(
188 http_proto::method m,
189 core::string_view t)
190 : request(
191 m, t, http_proto::version::http_1_1)
192 {
193 }
194
195 /** Constructor.
196
197 Allocates `cap` bytes initially, with an
198 upper limit of `max_cap`. Growing beyond
199 `max_cap` will throw an exception.
200
201 Useful when an estimated initial size is
202 known, but further growth up to a maximum
203 is allowed.
204
205 When `cap == max_cap`, the container
206 guarantees to never allocate.
207
208 @par Preconditions
209 @code
210 max_cap >= cap
211 @endcode
212
213 @par Exception Safety
214 Calls to allocate may throw.
215
216 @param cap Initial capacity in bytes (may be `0`).
217
218 @param max_cap Maximum allowed capacity in bytes.
219 */
220 10 request(
221 std::size_t cap,
222 std::size_t max_cap = std::size_t(-1))
223 10 : message_base(detail::kind::request)
224 {
225
1/1
✓ Branch 1 taken 10 times.
10 reserve_bytes(cap);
226
1/1
✓ Branch 1 taken 8 times.
10 set_max_capacity_in_bytes(max_cap);
227 10 }
228
229 /** Constructor.
230
231 The contents of `r` are transferred
232 to the newly constructed object,
233 which includes the underlying
234 character buffer.
235 After construction, the moved-from
236 object is as if default-constructed.
237
238 @par Postconditions
239 @code
240 r.buffer() == "GET / HTTP/1.1\r\n\r\n"
241 @endcode
242
243 @par Complexity
244 Constant.
245
246 @param r The request to move from.
247 */
248 25 request(
249 request&& other) noexcept
250 25 : message_base(detail::kind::request)
251 {
252 25 swap(other);
253 25 }
254
255 /** Constructor.
256
257 The newly constructed object contains
258 a copy of `r`.
259
260 @par Postconditions
261 @code
262 this->buffer() == r.buffer() && this->buffer.data() != r.buffer().data()
263 @endcode
264
265 @par Complexity
266 Linear in `r.size()`.
267
268 @par Exception Safety
269 Calls to allocate may throw.
270
271 @param r The request to copy.
272 */
273 4 request(
274 request const& r) = default;
275
276 /** Assignment
277
278 The contents of `r` are transferred to
279 `this`, including the underlying
280 character buffer. The previous contents
281 of `this` are destroyed.
282 After assignment, the moved-from
283 object is as if default-constructed.
284
285 @par Postconditions
286 @code
287 r.buffer() == "GET / HTTP/1.1\r\n\r\n"
288 @endcode
289
290 @par Complexity
291 Constant.
292
293 @param r The request to assign from.
294
295 @return A reference to this object.
296 */
297 request&
298 23 operator=(request&& r) noexcept
299 {
300 23 request temp(std::move(r));
301 23 temp.swap(*this);
302 46 return *this;
303 23 }
304
305 /** Assignment.
306
307 The contents of `r` are copied and
308 the previous contents of `this` are
309 discarded.
310
311 @par Postconditions
312 @code
313 this->buffer() == r.buffer() && this->buffer().data() != r.buffer().data()
314 @endcode
315
316 @par Complexity
317 Linear in `r.size()`.
318
319 @par Exception Safety
320 Strong guarantee.
321 Calls to allocate may throw.
322 Exception thrown if max capacity exceeded.
323
324 @throw std::length_error
325 Max capacity would be exceeded.
326
327 @param r The request to copy.
328
329 @return A reference to this object.
330 */
331 request&
332 3 operator=(
333 request const& r)
334 {
335 3 copy_impl(r.h_);
336 3 return *this;
337 }
338
339 //--------------------------------------------
340
341 /** Swap.
342
343 Exchanges the contents of this request
344 with another request. All views,
345 iterators and references remain valid.
346
347 If `this == &other`, this function call has no effect.
348
349 @par Example
350 @code
351 request r1(method::get, "/");
352 request r2(method::delete_, "/item/42");
353 r1.swap(r2);
354 assert(r1.buffer() == "DELETE /item/42 HTTP/1.1\r\n\r\n" );
355 assert(r2.buffer() == "GET / HTTP/1.1\r\n\r\n" );
356 @endcode
357
358 @par Complexity
359 Constant
360
361 @param other The object to swap with
362 */
363 void
364 48 swap(request& other) noexcept
365 {
366 48 h_.swap(other.h_);
367 48 std::swap(max_cap_, other.max_cap_);
368 48 std::swap(view_, other.view_);
369 48 }
370
371 /** Swap.
372
373 Exchanges the contents of `v0` with
374 another `v1`. All views, iterators and
375 references remain valid.
376
377 If `&v0 == &v1`, this function call has no effect.
378
379 @par Example
380 @code
381 request r1(method::get, "/");
382 request r2(method::delete_, "/item/42");
383 std::swap(r1, r2);
384 assert(r1.buffer() == "DELETE /item/42 HTTP/1.1\r\n\r\n" );
385 assert(r2.buffer() == "GET / HTTP/1.1\r\n\r\n" );
386 @endcode
387
388 @par Effects
389 @code
390 v0.swap(v1);
391 @endcode
392
393 @par Complexity
394 Constant.
395
396 @param v0 The first object to swap.
397 @param v1 The second object to swap.
398
399 @see
400 @ref request::swap
401 */
402 friend
403 void
404 swap(
405 request& v0,
406 request& v1) noexcept
407 {
408 v0.swap(v1);
409 }
410
411 //--------------------------------------------
412 //
413 // Observers
414 //
415 //--------------------------------------------
416
417 /** Return the method as a name constant.
418
419 If the method returned is equal to
420 @ref method::unknown, the method may
421 be obtained as a string instead, by
422 calling @ref method_text.
423 */
424 http_proto::method
425 76 method() const noexcept
426 {
427 76 return h_.req.method;
428 }
429
430 /** Return the method as a string.
431 */
432 core::string_view
433 83 method_text() const noexcept
434 {
435 166 return core::string_view(
436 83 h_.cbuf,
437 83 h_.req.method_len);
438 }
439
440 /** Return the request-target string.
441 */
442 core::string_view
443 73 target() const noexcept
444 {
445 146 return core::string_view(
446 73 h_.cbuf +
447 73 h_.req.method_len + 1,
448 73 h_.req.target_len);
449 }
450
451 //--------------------------------------------
452 //
453 // Modifiers
454 //
455 //--------------------------------------------
456
457 /** Set the method of the request to the enum.
458
459 @par Exception Safety
460 Strong guarantee.
461 Calls to allocate may throw.
462 Exception thrown if max capacity exceeded.
463
464 @throw std::length_error
465 Max capacity would be exceeded.
466
467 @param m The method to set.
468 */
469 void
470 2 set_method(
471 http_proto::method m)
472 {
473 2 set_start_line_impl(
474 m,
475 to_string(m),
476 target(),
477 version());
478 2 }
479
480 /** Set the method of the request to the string.
481
482 @par Exception Safety
483 Strong guarantee.
484 Calls to allocate may throw.
485 Exception thrown on invalid input.
486 Exception thrown if max capacity exceeded.
487
488 @throw system_error
489 Input is invalid.
490
491 @throw std::length_error
492 Max capacity would be exceeded.
493
494 @param s A string view representing the
495 method to set.
496 */
497 void
498 5 set_method(
499 core::string_view s)
500 {
501 5 set_start_line_impl(
502 string_to_method(s),
503 s,
504 target(),
505 version());
506 5 }
507
508 /** Set the target string of the request.
509
510 This function sets the request-target.
511 The caller is responsible for ensuring
512 that the string passed is syntactically
513 valid.
514
515 @par Exception Safety
516 Strong guarantee.
517 Calls to allocate may throw.
518 Exception thrown on invalid input.
519 Exception thrown if max capacity exceeded.
520
521 @throw system_error
522 Input is invalid.
523
524 @throw std::length_error
525 Max capacity would be exceeded.
526
527 @param s A string view representing the
528 target to set.
529 */
530 void
531 5 set_target(
532 core::string_view s)
533 {
534 5 set_start_line_impl(
535 h_.req.method,
536 method_text(),
537 s,
538 version());
539 5 }
540
541 /** Set the HTTP version of the request.
542
543 @par Exception Safety
544 Strong guarantee.
545 Calls to allocate may throw.
546 Exception thrown if max capacity exceeded.
547
548 @throw std::length_error
549 Max capacity would be exceeded.
550
551 @param v The version to set.
552 */
553 void
554 2 set_version(
555 http_proto::version v)
556 {
557 2 set_start_line_impl(
558 h_.req.method,
559 method_text(),
560 target(),
561 v);
562 2 }
563
564 /** Set the method, target, and version of the request.
565
566 This is more efficient than setting the
567 properties individually.
568
569 @par Exception Safety
570 Strong guarantee.
571 Calls to allocate may throw.
572 Exception thrown on invalid input.
573 Exception thrown if max capacity exceeded.
574
575 @throw system_error
576 Input is invalid.
577
578 @throw std::length_error
579 Max capacity would be exceeded.
580
581 @param m The method to set.
582
583 @param t A string view representing the
584 target to set.
585
586 @param v The version to set.
587 */
588 void
589 2 set_start_line(
590 http_proto::method m,
591 core::string_view t,
592 http_proto::version v =
593 http_proto::version::http_1_1)
594 {
595 2 set_start_line_impl(m, to_string(m), t, v);
596 1 }
597
598 /** Set the method, target, and version of the request.
599
600 This is more efficient than setting the
601 properties individually.
602
603 @par Exception Safety
604 Strong guarantee.
605 Calls to allocate may throw.
606 Exception thrown on invalid input.
607 Exception thrown if max capacity exceeded.
608
609 @throw system_error
610 Input is invalid.
611
612 @throw std::length_error
613 Max capacity would be exceeded.
614
615 @param m A string view representing the
616 method to set.
617
618 @param t A string view representing the
619 target to set.
620
621 @param v The version to set.
622 */
623 void
624 set_start_line(
625 core::string_view m,
626 core::string_view t,
627 http_proto::version v =
628 http_proto::version::http_1_1)
629 {
630 set_start_line_impl(string_to_method(m), m, t, v);
631 }
632
633 /** Set the `Expect: 100-continue` header.
634
635 @par Exception Safety
636 Strong guarantee.
637 Calls to allocate may throw.
638 Exception thrown if max capacity exceeded.
639
640 @throw std::length_error
641 Max capacity would be exceeded.
642
643 @param b If `true` sets `Expect: 100-continue`
644 header otherwise erase it.
645 */
646 BOOST_HTTP_PROTO_DECL
647 void
648 set_expect_100_continue(bool b);
649
650 private:
651 BOOST_HTTP_PROTO_DECL
652 void
653 set_start_line_impl(
654 http_proto::method m,
655 core::string_view ms,
656 core::string_view t,
657 http_proto::version v);
658 };
659
660 } // http_proto
661 } // boost
662
663 #endif
664