Line data Source code
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_view.
49 : */
50 : class response
51 : : public response_base
52 : {
53 : public:
54 :
55 : //--------------------------------------------
56 : //
57 : // Special Members
58 : //
59 : //--------------------------------------------
60 :
61 : /** Constructor.
62 :
63 : A default-constructed response contains
64 : a valid HTTP 200 OK response with no headers.
65 :
66 : @par Example
67 : @code
68 : response res;
69 : @endcode
70 :
71 : @par Postconditions
72 : @code
73 : this->buffer() == "HTTP/1.1 200 OK\r\n\r\n"
74 : @endcode
75 :
76 : @par Complexity
77 : Constant.
78 : */
79 : BOOST_HTTP_PROTO_DECL
80 : response() noexcept;
81 :
82 : /** Constructor.
83 :
84 : Constructs a response from the string `s`,
85 : which must contain valid HTTP response
86 : or else an exception is thrown.
87 : The new response retains ownership by
88 : making a copy of the passed string.
89 :
90 : @par Example
91 : @code
92 : response res(
93 : "HTTP/1.1 404 Not Found\r\n"
94 : "Server: Boost.HttpProto\r\n"
95 : "Content-Type: text/plain\r\n"
96 : "\r\n");
97 : @endcode
98 :
99 : @par Postconditions
100 : @code
101 : this->buffer.data() != s.data()
102 : @endcode
103 :
104 : @par Complexity
105 : Linear in `s.size()`.
106 :
107 : @par Exception Safety
108 : Calls to allocate may throw.
109 : Exception thrown on invalid input.
110 :
111 : @throw system_error
112 : The input does not contain a valid response.
113 :
114 : @param s The string to parse.
115 : */
116 : BOOST_HTTP_PROTO_DECL
117 : explicit
118 : response(
119 : core::string_view s);
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 : BOOST_HTTP_PROTO_DECL
147 : response(
148 : std::size_t cap,
149 : std::size_t max_cap = std::size_t(-1));
150 :
151 : /** Constructor.
152 :
153 : The start-line of the response will
154 : contain the standard text for the
155 : supplied status code and HTTP version.
156 :
157 : @par Example
158 : @code
159 : response res(status::not_found, version::http_1_0);
160 : @endcode
161 :
162 : @par Complexity
163 : Linear in `obsolete_reason(s).size()`.
164 :
165 : @par Exception Safety
166 : Calls to allocate may throw.
167 :
168 : @param sc The status code.
169 :
170 : @param v The HTTP version.
171 : */
172 : BOOST_HTTP_PROTO_DECL
173 : response(
174 : http_proto::status sc,
175 : http_proto::version v);
176 :
177 : /** Constructor.
178 :
179 : The start-line of the response will
180 : contain the standard text for the
181 : supplied status code with the HTTP version
182 : defaulted to `HTTP/1.1`.
183 :
184 : @par Example
185 : @code
186 : response res(status::not_found);
187 : @endcode
188 :
189 : @par Complexity
190 : Linear in `obsolete_reason(s).size()`.
191 :
192 : @par Exception Safety
193 : Calls to allocate may throw.
194 :
195 : @param sc The status code.
196 : */
197 : BOOST_HTTP_PROTO_DECL
198 : explicit
199 : response(
200 : http_proto::status sc);
201 :
202 : /** Constructor.
203 :
204 : The contents of `r` are transferred
205 : to the newly constructed object,
206 : which includes the underlying
207 : character buffer.
208 : After construction, the moved-from
209 : object is as if default-constructed.
210 :
211 : @par Postconditions
212 : @code
213 : r.buffer() == "HTTP/1.1 200 OK\r\n\r\n"
214 : @endcode
215 :
216 : @par Complexity
217 : Constant.
218 :
219 : @param r The response to move from.
220 : */
221 : BOOST_HTTP_PROTO_DECL
222 : response(response&& r) noexcept;
223 :
224 : /** Constructor.
225 :
226 : The newly constructed object contains
227 : a copy of `r`.
228 :
229 : @par Postconditions
230 : @code
231 : this->buffer() == r.buffer() && this->buffer.data() != r.buffer().data()
232 : @endcode
233 :
234 : @par Complexity
235 : Linear in `r.size()`.
236 :
237 : @par Exception Safety
238 : Calls to allocate may throw.
239 :
240 : @param r The response to copy.
241 : */
242 : BOOST_HTTP_PROTO_DECL
243 : response(response const& r);
244 :
245 : /** Constructor.
246 :
247 : The newly constructed object contains
248 : a copy of `r`.
249 :
250 : @par Postconditions
251 : @code
252 : this->buffer() == r.buffer() && this->buffer.data() != r.buffer().data()
253 : @endcode
254 :
255 : @par Complexity
256 : Linear in `r.size()`.
257 :
258 : @par Exception Safety
259 : Strong guarantee.
260 : Calls to allocate may throw.
261 :
262 : @param r The response to copy.
263 : */
264 : BOOST_HTTP_PROTO_DECL
265 : response(
266 : response_view const& r);
267 :
268 : /** Assignment
269 :
270 : The contents of `r` are transferred to
271 : `this`, including the underlying
272 : character buffer. The previous contents
273 : of `this` are destroyed.
274 : After assignment, the moved-from
275 : object is as if default-constructed.
276 :
277 : @par Postconditions
278 : @code
279 : r.buffer() == "HTTP/1.1 200 OK\r\n\r\n"
280 : @endcode
281 :
282 : @par Complexity
283 : Constant.
284 :
285 : @param r The response to assign from.
286 :
287 : @return A reference to this object.
288 : */
289 : BOOST_HTTP_PROTO_DECL
290 : response&
291 : operator=(
292 : response&& r) noexcept;
293 :
294 : /** Assignment.
295 :
296 : The contents of `r` are copied and
297 : the previous contents of `this` are
298 : discarded.
299 :
300 : @par Postconditions
301 : @code
302 : this->buffer() == r.buffer() && this->buffer().data() != r.buffer().data()
303 : @endcode
304 :
305 : @par Complexity
306 : Linear in `r.size()`.
307 :
308 : @par Exception Safety
309 : Strong guarantee.
310 : Calls to allocate may throw.
311 : Exception thrown if max capacity exceeded.
312 :
313 : @throw std::length_error
314 : Max capacity would be exceeded.
315 :
316 : @param r The response to copy.
317 :
318 : @return A reference to this object.
319 : */
320 : response&
321 1 : operator=(
322 : response const& r)
323 : {
324 1 : copy_impl(*r.ph_);
325 1 : return *this;
326 : }
327 :
328 : /** Assignment.
329 :
330 : The contents of `r` are copied and
331 : the previous contents of `this` are
332 : discarded.
333 :
334 : @par Postconditions
335 : @code
336 : this->buffer() == r.buffer() && this->buffer().data() != r.buffer().data()
337 : @endcode
338 :
339 : @par Complexity
340 : Linear in `r.size()`.
341 :
342 : @par Exception Safety
343 : Strong guarantee.
344 : Calls to allocate may throw.
345 : Exception thrown if max capacity exceeded.
346 :
347 : @throw std::length_error
348 : Max capacity would be exceeded.
349 :
350 : @param r The response to copy.
351 :
352 : @return A reference to this object.
353 : */
354 : response&
355 1 : operator=(
356 : response_view const& r)
357 : {
358 1 : copy_impl(*r.ph_);
359 1 : return *this;
360 : }
361 :
362 : //--------------------------------------------
363 :
364 : /** Swap.
365 :
366 : Exchanges the contents of this response
367 : with another response. All views,
368 : iterators and references remain valid.
369 :
370 : If `this == &other`, this function call has no effect.
371 :
372 : @par Example
373 : @code
374 : response r1(status::ok);
375 : response r2(status::bad_request);
376 : r1.swap(r2);
377 : assert(r1.buffer() == "HTTP/1.1 400 Bad Request\r\n\r\n" );
378 : assert(r2.buffer() == "HTTP/1.1 200 OK\r\n\r\n" );
379 : @endcode
380 :
381 : @par Complexity
382 : Constant
383 :
384 : @param other The object to swap with
385 : */
386 : void
387 4 : swap(response& other) noexcept
388 : {
389 4 : h_.swap(other.h_);
390 4 : std::swap(max_cap_, other.max_cap_);
391 4 : }
392 :
393 : /** Swap.
394 :
395 : Exchanges the contents of `v0` with
396 : another `v1`. All views, iterators and
397 : references remain valid.
398 :
399 : If `&v0 == &v1`, this function call has no effect.
400 :
401 : @par Example
402 : @code
403 : response r1(status::ok);
404 : response r2(status::bad_request);
405 : std::swap(r1, r2);
406 : assert(r1.buffer() == "HTTP/1.1 400 Bad Request\r\n\r\n" );
407 : assert(r2.buffer() == "HTTP/1.1 200 OK\r\n\r\n" );
408 : @endcode
409 :
410 : @par Effects
411 : @code
412 : v0.swap(v1);
413 : @endcode
414 :
415 : @par Complexity
416 : Constant.
417 :
418 : @param v0 The first object to swap.
419 : @param v1 The second object to swap.
420 :
421 : @see
422 : @ref response::swap.
423 : */
424 : friend
425 : void
426 : swap(
427 : response& v0,
428 : response& v1) noexcept
429 : {
430 : v0.swap(v1);
431 : }
432 : };
433 :
434 : } // http_proto
435 : } // boost
436 :
437 : #endif
|