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