Line data Source code
1 : //
2 : // Copyright (c) 2021 Vinnie Falco (vinnie.falco@gmail.com)
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_REQUEST_HPP
11 : #define BOOST_HTTP_PROTO_REQUEST_HPP
12 :
13 : #include <boost/http_proto/detail/config.hpp>
14 : #include <boost/http_proto/message_base.hpp>
15 : #include <boost/http_proto/request_view.hpp>
16 :
17 : namespace boost {
18 : namespace http_proto {
19 :
20 : /** Container for HTTP requests
21 : */
22 : class request final
23 : : public message_base
24 : {
25 : public:
26 : /** Constructor
27 : */
28 : BOOST_HTTP_PROTO_DECL
29 : request() noexcept;
30 :
31 : /** Constructor
32 : */
33 : BOOST_HTTP_PROTO_DECL
34 : explicit
35 : request(
36 : core::string_view s);
37 :
38 : /** Constructor
39 :
40 : Construct a request container which allocates
41 : `storage_size` bytes for storing the header.
42 : Attempting to grow the container beyond
43 : this amount will result in an exception.
44 : The storage is also used internally to store
45 : instances of an implementation-defined type.
46 : The requested number of bytes will be aligned
47 : accordingly (currently the alignment requirement is 4).
48 :
49 : <br/>
50 :
51 : This constructor is useful when an upper-bound size
52 : of the request is known ahead of time and we want
53 : to prevent reallocations.
54 :
55 : <br/>
56 :
57 : Passing an initial storage size of `0` does not
58 : throw and the maximum capacity is set to an
59 : implementation-defined limit observable via
60 : @ref max_capacity_in_bytes().
61 :
62 : @param storage_size The initial and final size of
63 : the storage.
64 :
65 : @code
66 : boost::http_proto::request
67 : make_request(std::string_view host)
68 : {
69 : std::size_t size = 4096;
70 : // req.buffer() is now stable
71 : boost::http_proto::request req(size);
72 : BOOST_ASSERT(
73 : req.max_capacity_in_bytes(), 4096);
74 :
75 : // uses spare capacity so that reallocations
76 : // are avoided
77 : req.append(
78 : boost::http_proto::field::host, host);
79 : req.append(
80 : boost::http_proto::field::connection, "close");
81 : return req;
82 : }
83 : @endcode
84 : */
85 : BOOST_HTTP_PROTO_DECL
86 : explicit
87 : request(
88 : std::size_t storage_size);
89 :
90 : /** Constructor
91 :
92 : Construct a request container which allocates
93 : `storage_size` bytes for storing the header, with an
94 : upper limit of `max_storage_size`. Attempting to
95 : grow the container beyond its maximum will result in
96 : an exception. The storage is also used internally to
97 : store instances of an implementation-defined type.
98 : Both values will be aligned accordingly (currently
99 : the alignment requirement is 4).
100 :
101 : <br/>
102 :
103 : This constructor is useful when there's a best-fit
104 : guess for an initial header size but we still wish
105 : to permit reallocating and growing the container to
106 : some upper limit.
107 :
108 : <br/>
109 :
110 : Passing an initial size of `0` does not throw.
111 :
112 : @param storage_size The initial size of the storage.
113 :
114 : @param max_storage_size The maximum size of the
115 : allocated storage. Any operation that attempts to
116 : grow the container beyond this value throws
117 : `std::length_error`.
118 :
119 : @throws std::length_error Thrown if `size > max_size`
120 :
121 : @code
122 : boost::http_proto::reqest
123 : make_reqest(std::string_view host)
124 : {
125 : std::size_t size = 4096;
126 : boost::http_proto::reqest req(size, 2 * size);
127 : BOOST_ASSERT(
128 : req.max_capacity_in_bytes(), 2 * 4096);
129 :
130 : // uses spare capacity so that reallocations
131 : // are avoided
132 : req.append(
133 : boost::http_proto::field::host, host);
134 : req.append(
135 : boost::http_proto::field::connection, "close");
136 : return req;
137 : }
138 : @endcode
139 : */
140 : BOOST_HTTP_PROTO_DECL
141 : request(
142 : std::size_t storage_size,
143 : std::size_t max_storage_size);
144 :
145 : /** Constructor
146 :
147 : The moved-from object will be
148 : left in the default-constructed
149 : state.
150 : */
151 : BOOST_HTTP_PROTO_DECL
152 : request(request&& other) noexcept;
153 :
154 : /** Constructor
155 : */
156 : BOOST_HTTP_PROTO_DECL
157 : request(request const& other);
158 :
159 : /** Constructor
160 : */
161 : BOOST_HTTP_PROTO_DECL
162 : request(
163 : request_view const& other);
164 :
165 : /** Assignment
166 : */
167 : BOOST_HTTP_PROTO_DECL
168 : request&
169 : operator=(request&&) noexcept;
170 :
171 : /** Assignment
172 : */
173 : request&
174 4 : operator=(request const& other)
175 : {
176 4 : copy_impl(*other.ph_);
177 4 : return *this;
178 : }
179 :
180 : /** Assignment
181 : */
182 : request&
183 : operator=(
184 : request_view const& other)
185 : {
186 : copy_impl(*other.ph_);
187 : return *this;
188 : }
189 :
190 : /** Return a read-only view to the request
191 : */
192 2 : operator
193 : request_view() const noexcept
194 : {
195 2 : return request_view(ph_);
196 : }
197 :
198 : //--------------------------------------------
199 : //
200 : // Observers
201 : //
202 : //--------------------------------------------
203 :
204 : /** Return the method as an integral constant
205 :
206 : If the method returned is equal to
207 : @ref method::unknown, the method may
208 : be obtained as a string instead, by
209 : calling @ref method_text.
210 : */
211 : http_proto::method
212 19 : method() const noexcept
213 : {
214 19 : return ph_->req.method;
215 : }
216 :
217 : /** Return the method as a string
218 : */
219 : core::string_view
220 26 : method_text() const noexcept
221 : {
222 52 : return core::string_view(
223 26 : ph_->cbuf,
224 26 : ph_->req.method_len);
225 : }
226 :
227 : /** Return the request-target string
228 : */
229 : core::string_view
230 19 : target() const noexcept
231 : {
232 38 : return core::string_view(
233 19 : ph_->cbuf +
234 19 : ph_->req.method_len + 1,
235 19 : ph_->req.target_len);
236 : }
237 :
238 : /** Return the HTTP-version
239 : */
240 : http_proto::version
241 27 : version() const noexcept
242 : {
243 27 : return ph_->version;
244 : }
245 :
246 : //--------------------------------------------
247 : //
248 : // Modifiers
249 : //
250 : //--------------------------------------------
251 :
252 : /** Set the method of the request to the enum
253 : */
254 : void
255 2 : set_method(
256 : http_proto::method m)
257 : {
258 2 : set_impl(
259 : m,
260 : to_string(m),
261 : target(),
262 : version());
263 2 : }
264 :
265 : /** Set the method of the request to the string
266 : */
267 : void
268 6 : set_method(
269 : core::string_view s)
270 : {
271 6 : set_impl(
272 : string_to_method(s),
273 : s,
274 : target(),
275 : version());
276 6 : }
277 :
278 : /** Set the target string of the request
279 :
280 : This function sets the request-target.
281 : The caller is responsible for ensuring
282 : that the string passed is syntactically
283 : valid.
284 : */
285 : void
286 5 : set_target(
287 : core::string_view s)
288 : {
289 5 : set_impl(
290 5 : ph_->req.method,
291 : method_text(),
292 : s,
293 : version());
294 5 : }
295 :
296 : /** Set the HTTP version of the request
297 : */
298 : void
299 2 : set_version(
300 : http_proto::version v)
301 : {
302 2 : set_impl(
303 2 : ph_->req.method,
304 : method_text(),
305 : target(),
306 : v);
307 2 : }
308 :
309 : /** Set the method, target, and version of the request
310 :
311 : This is more efficient than setting the
312 : properties individually.
313 : */
314 : void
315 1 : set_start_line(
316 : http_proto::method m,
317 : core::string_view t,
318 : http_proto::version v)
319 : {
320 1 : set_impl(m, to_string(m), t, v);
321 0 : }
322 :
323 : /** Set the method, target, and version of the request
324 :
325 : This is more efficient than setting the
326 : properties individually.
327 : */
328 : void
329 : set_start_line(
330 : core::string_view m,
331 : core::string_view t,
332 : http_proto::version v)
333 : {
334 : set_impl(string_to_method(m), m, t, v);
335 : }
336 :
337 : /** Set the Expect header
338 : */
339 : BOOST_HTTP_PROTO_DECL
340 : void
341 : set_expect_100_continue(bool b);
342 :
343 : //--------------------------------------------
344 :
345 : /** Swap this with another instance
346 : */
347 : void
348 44 : swap(request& other) noexcept
349 : {
350 44 : h_.swap(other.h_);
351 44 : }
352 :
353 : /** Swap two instances
354 : */
355 : // hidden friend
356 : friend
357 : void
358 : swap(
359 : request& t0,
360 : request& t1) noexcept
361 : {
362 : t0.swap(t1);
363 : }
364 :
365 : private:
366 : BOOST_HTTP_PROTO_DECL
367 : void
368 : set_impl(
369 : http_proto::method m,
370 : core::string_view ms,
371 : core::string_view t,
372 : http_proto::version v);
373 : };
374 :
375 : } // http_proto
376 : } // boost
377 :
378 : #endif
|