]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/beast/http/impl/message.ipp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / beast / http / impl / message.ipp
1 //
2 // Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot 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/boostorg/beast
8 //
9
10 #ifndef BOOST_BEAST_HTTP_IMPL_MESSAGE_IPP
11 #define BOOST_BEAST_HTTP_IMPL_MESSAGE_IPP
12
13 #include <boost/beast/core/error.hpp>
14 #include <boost/beast/core/detail/type_traits.hpp>
15 #include <boost/assert.hpp>
16 #include <boost/throw_exception.hpp>
17 #include <stdexcept>
18
19 namespace boost {
20 namespace beast {
21 namespace http {
22
23 template<class Fields>
24 template<class Arg1, class... ArgN, class>
25 header<true, Fields>::
26 header(Arg1&& arg1, ArgN&&... argn)
27 : Fields(std::forward<Arg1>(arg1),
28 std::forward<ArgN>(argn)...)
29 {
30 }
31
32 template<class Fields>
33 inline
34 verb
35 header<true, Fields>::
36 method() const
37 {
38 return method_;
39 }
40
41 template<class Fields>
42 void
43 header<true, Fields>::
44 method(verb v)
45 {
46 if(v == verb::unknown)
47 BOOST_THROW_EXCEPTION(
48 std::invalid_argument{"unknown method"});
49 method_ = v;
50 this->set_method_impl({});
51 }
52
53 template<class Fields>
54 string_view
55 header<true, Fields>::
56 method_string() const
57 {
58 if(method_ != verb::unknown)
59 return to_string(method_);
60 return this->get_method_impl();
61 }
62
63 template<class Fields>
64 void
65 header<true, Fields>::
66 method_string(string_view s)
67 {
68 method_ = string_to_verb(s);
69 if(method_ != verb::unknown)
70 this->set_method_impl({});
71 else
72 this->set_method_impl(s);
73 }
74
75 template<class Fields>
76 inline
77 string_view
78 header<true, Fields>::
79 target() const
80 {
81 return this->get_target_impl();
82 }
83
84 template<class Fields>
85 inline
86 void
87 header<true, Fields>::
88 target(string_view s)
89 {
90 this->set_target_impl(s);
91 }
92
93 template<class Fields>
94 void
95 swap(
96 header<true, Fields>& h1,
97 header<true, Fields>& h2)
98 {
99 using std::swap;
100 swap(
101 static_cast<Fields&>(h1),
102 static_cast<Fields&>(h2));
103 swap(h1.version_, h2.version_);
104 swap(h1.method_, h2.method_);
105 }
106
107 //------------------------------------------------------------------------------
108
109 template<class Fields>
110 template<class Arg1, class... ArgN, class>
111 header<false, Fields>::
112 header(Arg1&& arg1, ArgN&&... argn)
113 : Fields(std::forward<Arg1>(arg1),
114 std::forward<ArgN>(argn)...)
115 {
116 }
117
118 template<class Fields>
119 inline
120 status
121 header<false, Fields>::
122 result() const
123 {
124 return int_to_status(
125 static_cast<int>(result_));
126 }
127
128 template<class Fields>
129 inline
130 void
131 header<false, Fields>::
132 result(status v)
133 {
134 result_ = v;
135 }
136
137 template<class Fields>
138 inline
139 void
140 header<false, Fields>::
141 result(unsigned v)
142 {
143 if(v > 999)
144 BOOST_THROW_EXCEPTION(
145 std::invalid_argument{
146 "invalid status-code"});
147 result_ = static_cast<status>(v);
148 }
149
150 template<class Fields>
151 inline
152 unsigned
153 header<false, Fields>::
154 result_int() const
155 {
156 return static_cast<unsigned>(result_);
157 }
158
159 template<class Fields>
160 string_view
161 header<false, Fields>::
162 reason() const
163 {
164 auto const s = this->get_reason_impl();
165 if(! s.empty())
166 return s;
167 return obsolete_reason(result_);
168 }
169
170 template<class Fields>
171 inline
172 void
173 header<false, Fields>::
174 reason(string_view s)
175 {
176 this->set_reason_impl(s);
177 }
178
179 template<class Fields>
180 void
181 swap(
182 header<false, Fields>& h1,
183 header<false, Fields>& h2)
184 {
185 using std::swap;
186 swap(
187 static_cast<Fields&>(h1),
188 static_cast<Fields&>(h2));
189 swap(h1.version_, h2.version_);
190 swap(h1.result_, h2.result_);
191 }
192
193 //------------------------------------------------------------------------------
194
195 template<bool isRequest, class Body, class Fields>
196 template<class... BodyArgs>
197 message<isRequest, Body, Fields>::
198 message(header_type&& h, BodyArgs&&... body_args)
199 : header_type(std::move(h))
200 , beast::detail::empty_base_optimization<
201 typename Body::value_type>(
202 std::forward<BodyArgs>(body_args)...)
203 {
204 }
205
206 template<bool isRequest, class Body, class Fields>
207 template<class... BodyArgs>
208 message<isRequest, Body, Fields>::
209 message(header_type const& h, BodyArgs&&... body_args)
210 : header_type(h)
211 , beast::detail::empty_base_optimization<
212 typename Body::value_type>(
213 std::forward<BodyArgs>(body_args)...)
214 {
215 }
216
217 template<bool isRequest, class Body, class Fields>
218 template<class Version, class>
219 message<isRequest, Body, Fields>::
220 message(verb method, string_view target, Version version)
221 : header_type(method, target, version)
222 {
223 }
224
225 template<bool isRequest, class Body, class Fields>
226 template<class Version, class BodyArg, class>
227 message<isRequest, Body, Fields>::
228 message(verb method, string_view target,
229 Version version, BodyArg&& body_arg)
230 : header_type(method, target, version)
231 , beast::detail::empty_base_optimization<
232 typename Body::value_type>(
233 std::forward<BodyArg>(body_arg))
234 {
235 }
236
237 template<bool isRequest, class Body, class Fields>
238 template<class Version, class BodyArg, class FieldsArg, class>
239 message<isRequest, Body, Fields>::
240 message(
241 verb method, string_view target, Version version,
242 BodyArg&& body_arg,
243 FieldsArg&& fields_arg)
244 : header_type(method, target, version,
245 std::forward<FieldsArg>(fields_arg))
246 , beast::detail::empty_base_optimization<
247 typename Body::value_type>(
248 std::forward<BodyArg>(body_arg))
249 {
250 }
251
252 template<bool isRequest, class Body, class Fields>
253 template<class Version, class>
254 message<isRequest, Body, Fields>::
255 message(status result, Version version)
256 : header_type(result, version)
257 {
258 }
259
260 template<bool isRequest, class Body, class Fields>
261 template<class Version, class BodyArg, class>
262 message<isRequest, Body, Fields>::
263 message(status result, Version version,
264 BodyArg&& body_arg)
265 : header_type(result, version)
266 , beast::detail::empty_base_optimization<
267 typename Body::value_type>(
268 std::forward<BodyArg>(body_arg))
269 {
270 }
271
272 template<bool isRequest, class Body, class Fields>
273 template<class Version, class BodyArg, class FieldsArg, class>
274 message<isRequest, Body, Fields>::
275 message(status result, Version version,
276 BodyArg&& body_arg, FieldsArg&& fields_arg)
277 : header_type(result, version,
278 std::forward<FieldsArg>(fields_arg))
279 , beast::detail::empty_base_optimization<
280 typename Body::value_type>(
281 std::forward<BodyArg>(body_arg))
282 {
283 }
284
285 template<bool isRequest, class Body, class Fields>
286 message<isRequest, Body, Fields>::
287 message(std::piecewise_construct_t)
288 {
289 }
290
291 template<bool isRequest, class Body, class Fields>
292 template<class... BodyArgs>
293 message<isRequest, Body, Fields>::
294 message(std::piecewise_construct_t,
295 std::tuple<BodyArgs...> body_args)
296 : message(std::piecewise_construct,
297 body_args,
298 beast::detail::make_index_sequence<
299 sizeof...(BodyArgs)>{})
300 {
301 }
302
303 template<bool isRequest, class Body, class Fields>
304 template<class... BodyArgs, class... FieldsArgs>
305 message<isRequest, Body, Fields>::
306 message(std::piecewise_construct_t,
307 std::tuple<BodyArgs...> body_args,
308 std::tuple<FieldsArgs...> fields_args)
309 : message(std::piecewise_construct,
310 body_args,
311 fields_args,
312 beast::detail::make_index_sequence<
313 sizeof...(BodyArgs)>{},
314 beast::detail::make_index_sequence<
315 sizeof...(FieldsArgs)>{})
316 {
317 }
318
319 template<bool isRequest, class Body, class Fields>
320 void
321 message<isRequest, Body, Fields>::
322 chunked(bool value)
323 {
324 this->set_chunked_impl(value);
325 this->set_content_length_impl(boost::none);
326 }
327
328 template<bool isRequest, class Body, class Fields>
329 void
330 message<isRequest, Body, Fields>::
331 content_length(
332 boost::optional<std::uint64_t> const& value)
333 {
334 this->set_content_length_impl(value);
335 this->set_chunked_impl(false);
336 }
337
338 template<bool isRequest, class Body, class Fields>
339 boost::optional<std::uint64_t>
340 message<isRequest, Body, Fields>::
341 payload_size() const
342 {
343 return payload_size(detail::is_body_sized<Body>{});
344 }
345
346 template<bool isRequest, class Body, class Fields>
347 bool
348 message<isRequest, Body, Fields>::
349 need_eof(std::false_type) const
350 {
351 // VFALCO Do we need a way to let the caller say "the body is intentionally skipped"?
352 if( this->result() == status::no_content ||
353 this->result() == status::not_modified ||
354 to_status_class(this->result()) ==
355 status_class::informational ||
356 has_content_length() ||
357 chunked())
358 return ! keep_alive();
359 return true;
360 }
361
362 template<bool isRequest, class Body, class Fields>
363 void
364 message<isRequest, Body, Fields>::
365 prepare_payload(std::true_type)
366 {
367 auto const n = payload_size();
368 if(this->method() == verb::trace && (! n || *n > 0))
369 BOOST_THROW_EXCEPTION(std::invalid_argument{
370 "invalid request body"});
371 if(n)
372 {
373 if(*n > 0 ||
374 this->method() == verb::options ||
375 this->method() == verb::put ||
376 this->method() == verb::post)
377 {
378 this->content_length(n);
379 }
380 else
381 {
382 this->chunked(false);
383 }
384 }
385 else if(this->version() == 11)
386 {
387 this->chunked(true);
388 }
389 else
390 {
391 this->chunked(false);
392 }
393 }
394
395 template<bool isRequest, class Body, class Fields>
396 void
397 message<isRequest, Body, Fields>::
398 prepare_payload(std::false_type)
399 {
400 auto const n = payload_size();
401 if( (! n || *n > 0) && (
402 (status_class(this->result()) == status_class::informational ||
403 this->result() == status::no_content ||
404 this->result() == status::not_modified)))
405 {
406 // The response body MUST be empty for this case
407 BOOST_THROW_EXCEPTION(std::invalid_argument{
408 "invalid response body"});
409 }
410 if(n)
411 this->content_length(n);
412 else if(this->version() == 11)
413 this->chunked(true);
414 else
415 this->chunked(false);
416 }
417
418 //------------------------------------------------------------------------------
419
420 template<bool isRequest, class Body, class Fields>
421 void
422 swap(
423 message<isRequest, Body, Fields>& m1,
424 message<isRequest, Body, Fields>& m2)
425 {
426 using std::swap;
427 swap(
428 static_cast<header<isRequest, Fields>&>(m1),
429 static_cast<header<isRequest, Fields>&>(m2));
430 swap(m1.body(), m2.body());
431 }
432
433 } // http
434 } // beast
435 } // boost
436
437 #endif