GCC Code Coverage Report


Directory: libs/http_proto/
File: include/boost/http_proto/response.hpp
Date: 2025-10-12 23:51:57
Exec Total Coverage
Lines: 40 40 100.0%
Functions: 12 12 100.0%
Branches: 4 6 66.7%

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