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