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