GCC Code Coverage Report


Directory: ./
File: libs/http_proto/include/boost/http_proto/response.hpp
Date: 2025-12-09 20:49:49
Exec Total Coverage
Lines: 40 40 100.0%
Functions: 12 12 100.0%
Branches: 3 3 100.0%

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