Line data Source code
1 : //
2 : // Copyright (c) 2025 Mohammad Nejati
3 : //
4 : // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 : //
7 : // Official repository: https://github.com/cppalliance/http_proto
8 : //
9 :
10 : #ifndef BOOST_HTTP_PROTO_STATIC_RESPONSE_HPP
11 : #define BOOST_HTTP_PROTO_STATIC_RESPONSE_HPP
12 :
13 : #include <boost/http_proto/response_base.hpp>
14 :
15 : namespace boost {
16 : namespace http_proto {
17 :
18 : /** A modifiable static container for HTTP responses.
19 :
20 : This container owns a response, represented
21 : by an inline buffer with fixed capacity.
22 : The contents may be inspected and modified,
23 : and the implementation maintains a useful
24 : invariant: changes to the response always
25 : leave it in a valid state.
26 :
27 : @par Example
28 : @code
29 : static_response<1024> res(status::not_found);
30 :
31 : res.set(field::server, "Boost.HttpProto");
32 : res.set(field::content_type, "text/plain");
33 : res.set_content_length(80);
34 :
35 : assert(res.buffer() ==
36 : "HTTP/1.1 404 Not Found\r\n"
37 : "Server: Boost.HttpProto\r\n"
38 : "Content-Type: text/plain\r\n"
39 : "Content-Length: 80\r\n"
40 : "\r\n");
41 : @endcode
42 :
43 : @par Invariants
44 : @code
45 : this->capacity_in_bytes() == Capacity && this->max_capacity_in_bytes() == Capacity
46 : @endcode
47 :
48 : @tparam Capacity The maximum capacity in bytes.
49 :
50 : @see
51 : @ref response,
52 : @ref response_view.
53 : */
54 : template<std::size_t Capacity>
55 : class static_response
56 : : public response_base
57 : {
58 : alignas(entry)
59 : char buf_[Capacity];
60 :
61 : public:
62 :
63 : //--------------------------------------------
64 : //
65 : // Special Members
66 : //
67 : //--------------------------------------------
68 :
69 : /** Constructor.
70 :
71 : A default-constructed response contains
72 : a valid HTTP 200 OK response with no headers.
73 :
74 : @par Example
75 : @code
76 : static_response<1024> res;
77 : @endcode
78 :
79 : @par Postconditions
80 : @code
81 : this->buffer() == "HTTP/1.1 200 OK\r\n\r\n"
82 : @endcode
83 :
84 : @par Complexity
85 : Constant.
86 : */
87 20 : static_response() noexcept
88 20 : : fields_view_base(&this->fields_base::h_)
89 20 : , response_base(buf_, Capacity)
90 : {
91 20 : }
92 :
93 : /** Constructor.
94 :
95 : Constructs a response from the string `s`,
96 : which must contain valid HTTP response
97 : or else an exception is thrown.
98 : The new response retains ownership by
99 : making a copy of the passed string.
100 :
101 : @par Example
102 : @code
103 : static_response<1024> res(
104 : "HTTP/1.1 404 Not Found\r\n"
105 : "Server: Boost.HttpProto\r\n"
106 : "Content-Type: text/plain\r\n"
107 : "\r\n");
108 : @endcode
109 :
110 : @par Postconditions
111 : @code
112 : this->buffer.data() != s.data()
113 : @endcode
114 :
115 : @par Complexity
116 : Linear in `s.size()`.
117 :
118 : @par Exception Safety
119 : Exception thrown on invalid input.
120 : Exception thrown if max capacity exceeded.
121 :
122 : @throw system_error
123 : The input does not contain a valid response.
124 :
125 : @throw std::length_error
126 : Max capacity would be exceeded.
127 :
128 : @param s The string to parse.
129 : */
130 : explicit
131 3 : static_response(
132 : core::string_view s)
133 3 : : fields_view_base(&this->fields_base::h_)
134 3 : , response_base(s, buf_, Capacity)
135 : {
136 3 : }
137 :
138 : /** Constructor.
139 :
140 : The start-line of the response will
141 : contain the standard text for the
142 : supplied status code and HTTP version.
143 :
144 : @par Example
145 : @code
146 : static_response<1024> res(status::not_found, version::http_1_0);
147 : @endcode
148 :
149 : @par Complexity
150 : Linear in `obsolete_reason(s).size()`.
151 :
152 : @par Exception Safety
153 : Exception thrown if max capacity exceeded.
154 :
155 : @throw std::length_error
156 : Max capacity would be exceeded.
157 :
158 : @param sc The status code.
159 :
160 : @param v The HTTP version.
161 : */
162 10 : static_response(
163 : http_proto::status sc,
164 : http_proto::version v)
165 10 : : static_response()
166 : {
167 10 : set_start_line(sc, v);
168 10 : }
169 :
170 : /** Constructor.
171 :
172 : The start-line of the response will
173 : contain the standard text for the
174 : supplied status code with the HTTP version
175 : defaulted to `HTTP/1.1`.
176 :
177 : @par Example
178 : @code
179 : static_response<1024> res(status::not_found);
180 : @endcode
181 :
182 : @par Complexity
183 : Linear in `obsolete_reason(s).size()`.
184 :
185 : @par Exception Safety
186 : Exception thrown if max capacity exceeded.
187 :
188 : @throw std::length_error
189 : Max capacity would be exceeded.
190 :
191 : @param sc The status code.
192 : */
193 : explicit
194 4 : static_response(
195 : http_proto::status sc)
196 : : static_response(
197 4 : sc, http_proto::version::http_1_1)
198 : {
199 4 : }
200 :
201 : /** Constructor.
202 :
203 : The newly constructed object contains
204 : a copy of `r`.
205 :
206 : @par Postconditions
207 : @code
208 : this->buffer() == r.buffer() && this->buffer.data() != r.buffer().data()
209 : @endcode
210 :
211 : @par Complexity
212 : Linear in `r.size()`.
213 :
214 : @param r The response to copy.
215 : */
216 2 : static_response(
217 : static_response const& r) noexcept
218 2 : : fields_view_base(&this->fields_base::h_)
219 2 : , response_base(*r.ph_, buf_, Capacity)
220 : {
221 2 : }
222 :
223 : /** Constructor.
224 :
225 : The newly constructed object contains
226 : a copy of `r`.
227 :
228 : @par Postconditions
229 : @code
230 : this->buffer() == r.buffer() && this->buffer.data() != r.buffer().data()
231 : @endcode
232 :
233 : @par Complexity
234 : Linear in `r.size()`.
235 :
236 : @par Exception Safety
237 : Exception thrown if max capacity exceeded.
238 :
239 : @throw std::length_error
240 : Max capacity would be exceeded.
241 :
242 : @param r The response to copy.
243 : */
244 2 : static_response(
245 : response_view const& r)
246 2 : : fields_view_base(&this->fields_base::h_)
247 2 : , response_base(*r.ph_, buf_, Capacity)
248 : {
249 2 : }
250 :
251 : /** Assignment.
252 :
253 : The contents of `r` are copied and
254 : the previous contents of `this` are
255 : discarded.
256 :
257 : @par Postconditions
258 : @code
259 : this->buffer() == r.buffer() && this->buffer().data() != r.buffer().data()
260 : @endcode
261 :
262 : @par Complexity
263 : Linear in `r.size()`.
264 :
265 : @param r The response to copy.
266 :
267 : @return A reference to this object.
268 : */
269 : static_response&
270 1 : operator=(
271 : static_response const& r) noexcept
272 : {
273 1 : copy_impl(*r.ph_);
274 1 : return *this;
275 : }
276 :
277 : /** Assignment.
278 :
279 : The contents of `r` are copied and
280 : the previous contents of `this` are
281 : discarded.
282 :
283 : @par Postconditions
284 : @code
285 : this->buffer() == r.buffer() && this->buffer().data() != r.buffer().data()
286 : @endcode
287 :
288 : @par Complexity
289 : Linear in `r.size()`.
290 :
291 : @par Exception Safety
292 : Strong guarantee.
293 : Exception thrown if max capacity exceeded.
294 :
295 : @throw std::length_error
296 : Max capacity would be exceeded.
297 :
298 : @param r The response to copy.
299 :
300 : @return A reference to this object.
301 : */
302 : static_response&
303 1 : operator=(
304 : response_view const& r)
305 : {
306 1 : copy_impl(*r.ph_);
307 1 : return *this;
308 : }
309 : };
310 :
311 : } // http_proto
312 : } // boost
313 :
314 : #endif
|