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_REQUEST_HPP
11 : #define BOOST_HTTP_PROTO_STATIC_REQUEST_HPP
12 :
13 : #include <boost/http_proto/request_base.hpp>
14 :
15 : namespace boost {
16 : namespace http_proto {
17 :
18 : /** A modifiable static container for HTTP requests.
19 :
20 : This container owns a request, 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 request always
25 : leave it in a valid state.
26 :
27 : @par Example
28 : @code
29 : static_request<1024> req(method::get, "/");
30 :
31 : req.set(field::host, "example.com");
32 : req.set(field::accept_encoding, "gzip, deflate, br");
33 : req.set(field::cache_control, "no-cache");
34 :
35 : assert(req.buffer() ==
36 : "GET / HTTP/1.1\r\n"
37 : "Host: example.com\r\n"
38 : "Accept-Encoding: gzip, deflate, br\r\n"
39 : "Cache-Control: no-cache\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 request,
52 : @ref request_view.
53 : */
54 : template<std::size_t Capacity>
55 : class static_request
56 : : public request_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 request contains
72 : a valid HTTP `GET` request with no headers.
73 :
74 : @par Example
75 : @code
76 : static_request<1024> req;
77 : @endcode
78 :
79 : @par Postconditions
80 : @code
81 : this->buffer() == "GET / HTTP/1.1\r\n\r\n"
82 : @endcode
83 :
84 : @par Complexity
85 : Constant.
86 : */
87 20 : static_request() noexcept
88 20 : : fields_view_base(&this->fields_base::h_)
89 20 : , request_base(buf_, Capacity)
90 : {
91 20 : }
92 :
93 : /** Constructor.
94 :
95 : Constructs a request from the string `s`,
96 : which must contain valid HTTP request
97 : or else an exception is thrown.
98 : The new request retains ownership by
99 : making a copy of the passed string.
100 :
101 : @par Example
102 : @code
103 : static_request<1024> req(
104 : "GET / HTTP/1.1\r\n"
105 : "Accept-Encoding: gzip, deflate, br\r\n"
106 : "Cache-Control: no-cache\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 request.
124 :
125 : @throw std::length_error
126 : Max capacity would be exceeded.
127 :
128 : @param s The string to parse.
129 : */
130 : explicit
131 22 : static_request(
132 : core::string_view s)
133 22 : : fields_view_base(&this->fields_base::h_)
134 22 : , request_base(s, buf_, Capacity)
135 : {
136 22 : }
137 :
138 : /** Constructor.
139 :
140 : The start-line of the request will
141 : contain the standard text for the
142 : supplied method, target and HTTP version.
143 :
144 : @par Example
145 : @code
146 : static_request<1024> req(method::get, "/index.html", version::http_1_0);
147 : @endcode
148 :
149 : @par Complexity
150 : Linear in `to_string(m).size() + t.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 m The method to set.
159 :
160 : @param t The string representing a target.
161 :
162 : @param v The version to set.
163 : */
164 : static_request(
165 : http_proto::method m,
166 : core::string_view t,
167 : http_proto::version v) noexcept
168 : : static_request()
169 : {
170 : set_start_line(m, t, v);
171 : }
172 :
173 : /** Constructor.
174 :
175 : The start-line of the request will
176 : contain the standard text for the
177 : supplied method and target with the HTTP
178 : version defaulted to `HTTP/1.1`.
179 :
180 : @par Example
181 : @code
182 : static_request<1024> req(method::get, "/index.html");
183 : @endcode
184 :
185 : @par Complexity
186 : Linear in `obsolete_reason(s).size()`.
187 :
188 : @par Exception Safety
189 : Exception thrown if max capacity exceeded.
190 :
191 : @throw std::length_error
192 : Max capacity would be exceeded.
193 :
194 : @param m The method to set.
195 :
196 : @param t The string representing a target.
197 : */
198 : static_request(
199 : http_proto::method m,
200 : core::string_view t)
201 : : static_request(
202 : m, t, http_proto::version::http_1_1)
203 : {
204 : }
205 :
206 : /** Constructor.
207 :
208 : The newly constructed object contains
209 : a copy of `r`.
210 :
211 : @par Postconditions
212 : @code
213 : this->buffer() == r.buffer() && this->buffer.data() != r.buffer().data()
214 : @endcode
215 :
216 : @par Complexity
217 : Linear in `r.size()`.
218 :
219 : @param r The request to copy.
220 : */
221 2 : static_request(
222 : static_request const& r) noexcept
223 2 : : fields_view_base(&this->fields_base::h_)
224 2 : , request_base(*r.ph_, buf_, Capacity)
225 : {
226 2 : }
227 :
228 : /** Constructor.
229 :
230 : The newly constructed object contains
231 : a copy of `r`.
232 :
233 : @par Postconditions
234 : @code
235 : this->buffer() == r.buffer() && this->buffer.data() != r.buffer().data()
236 : @endcode
237 :
238 : @par Complexity
239 : Linear in `r.size()`.
240 :
241 : @par Exception Safety
242 : Exception thrown if max capacity exceeded.
243 :
244 : @throw std::length_error
245 : Max capacity would be exceeded.
246 :
247 : @param r The request to copy.
248 : */
249 2 : static_request(
250 : request_view const& r)
251 2 : : fields_view_base(&this->fields_base::h_)
252 2 : , request_base(*r.ph_, buf_, Capacity)
253 : {
254 2 : }
255 :
256 : /** Assignment.
257 :
258 : The contents of `r` are copied and
259 : the previous contents of `this` are
260 : discarded.
261 :
262 : @par Postconditions
263 : @code
264 : this->buffer() == r.buffer() && this->buffer().data() != r.buffer().data()
265 : @endcode
266 :
267 : @par Complexity
268 : Linear in `r.size()`.
269 :
270 : @param r The request to copy.
271 :
272 : @return A reference to this object.
273 : */
274 : static_request&
275 9 : operator=(
276 : static_request const& r) noexcept
277 : {
278 9 : copy_impl(*r.ph_);
279 9 : return *this;
280 : }
281 :
282 : /** Assignment.
283 :
284 : The contents of `r` are copied and
285 : the previous contents of `this` are
286 : discarded.
287 :
288 : @par Postconditions
289 : @code
290 : this->buffer() == r.buffer() && this->buffer().data() != r.buffer().data()
291 : @endcode
292 :
293 : @par Complexity
294 : Linear in `r.size()`.
295 :
296 : @par Exception Safety
297 : Strong guarantee.
298 : Exception thrown if max capacity exceeded.
299 :
300 : @throw std::length_error
301 : Max capacity would be exceeded.
302 :
303 : @param r The request to copy.
304 :
305 : @return A reference to this object.
306 : */
307 : static_request&
308 : operator=(
309 : request_view const& r)
310 : {
311 : copy_impl(*r.ph_);
312 : return *this;
313 : }
314 : };
315 :
316 : } // http_proto
317 : } // boost
318 :
319 : #endif
|