]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/beast/http/chunk_encode.hpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / boost / beast / http / chunk_encode.hpp
CommitLineData
b32b8144 1//
92f5a8d4 2// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
b32b8144
FG
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_CHUNK_ENCODE_HPP
11#define BOOST_BEAST_HTTP_CHUNK_ENCODE_HPP
12
13#include <boost/beast/core/detail/config.hpp>
14#include <boost/beast/core/buffers_cat.hpp>
15#include <boost/beast/core/string.hpp>
16#include <boost/beast/http/type_traits.hpp>
17#include <boost/beast/http/detail/chunk_encode.hpp>
18#include <boost/asio/buffer.hpp>
19#include <memory>
20#include <type_traits>
21
22namespace boost {
23namespace beast {
24namespace http {
25
26/** A chunked encoding crlf
27
92f5a8d4 28 This implements a <em>ConstBufferSequence</em> holding the CRLF
b32b8144
FG
29 (`"\r\n"`) used as a delimiter in a @em chunk.
30
31 To use this class, pass an instance of it to a
32 stream algorithm as the buffer sequence:
33 @code
34 // writes "\r\n"
92f5a8d4 35 net::write(stream, chunk_crlf{});
b32b8144
FG
36 @endcode
37
38 @see https://tools.ietf.org/html/rfc7230#section-4.1
39*/
40struct chunk_crlf
41{
42 /// Constructor
43 chunk_crlf() = default;
44
45 //-----
46
92f5a8d4 47 /// Required for <em>ConstBufferSequence</em>
b32b8144 48#if BOOST_BEAST_DOXYGEN
92f5a8d4 49 using value_type = __implementation_defined__;
b32b8144 50#else
92f5a8d4 51 using value_type = net::const_buffer;
b32b8144
FG
52#endif
53
92f5a8d4 54 /// Required for <em>ConstBufferSequence</em>
b32b8144
FG
55 using const_iterator = value_type const*;
56
92f5a8d4 57 /// Required for <em>ConstBufferSequence</em>
b32b8144
FG
58 chunk_crlf(chunk_crlf const&) = default;
59
92f5a8d4 60 /// Required for <em>ConstBufferSequence</em>
b32b8144
FG
61 const_iterator
62 begin() const
63 {
92f5a8d4
TL
64 static net::const_buffer const cb{"\r\n", 2};
65 return &cb;
b32b8144
FG
66 }
67
92f5a8d4 68 /// Required for <em>ConstBufferSequence</em>
b32b8144
FG
69 const_iterator
70 end() const
71 {
72 return begin() + 1;
73 }
74};
75
76//------------------------------------------------------------------------------
77
78/** A @em chunk header
79
92f5a8d4 80 This implements a <em>ConstBufferSequence</em> representing the
b32b8144
FG
81 header of a @em chunk. The serialized format is as follows:
82 @code
83 chunk-header = 1*HEXDIG chunk-ext CRLF
84 chunk-ext = *( ";" chunk-ext-name [ "=" chunk-ext-val ] )
85 chunk-ext-name = token
86 chunk-ext-val = token / quoted-string
87 @endcode
88 The chunk extension is optional. After the header and
89 chunk body have been serialized, it is the callers
90 responsibility to also serialize the final CRLF (`"\r\n"`).
91
92 This class allows the caller to emit piecewise chunk bodies,
93 by first serializing the chunk header using this class and then
94 serializing the chunk body in a series of one or more calls to
95 a stream write operation.
96
97 To use this class, pass an instance of it to a
98 stream algorithm as the buffer sequence:
99 @code
100 // writes "400;x\r\n"
92f5a8d4 101 net::write(stream, chunk_header{1024, "x"});
b32b8144
FG
102 @endcode
103
104 @see https://tools.ietf.org/html/rfc7230#section-4.1
105*/
106class chunk_header
107{
108 using view_type = buffers_cat_view<
109 detail::chunk_size, // chunk-size
92f5a8d4 110 net::const_buffer, // chunk-extensions
b32b8144
FG
111 chunk_crlf>; // CRLF
112
113 std::shared_ptr<
114 detail::chunk_extensions> exts_;
115 view_type view_;
116
117public:
118 /** Constructor
119
120 This constructs a buffer sequence representing a
121 @em chunked-body size and terminating CRLF (`"\r\n"`)
122 with no chunk extensions.
123
124 @param size The size of the chunk body that follows.
125 The value must be greater than zero.
126
127 @see https://tools.ietf.org/html/rfc7230#section-4.1
128 */
129 explicit
130 chunk_header(std::size_t size);
131
132 /** Constructor
133
134 This constructs a buffer sequence representing a
135 @em chunked-body size and terminating CRLF (`"\r\n"`)
136 with provided chunk extensions.
137
138 @param size The size of the chunk body that follows.
139 The value must be greater than zero.
140
141 @param extensions The chunk extensions string. This
142 string must be formatted correctly as per rfc7230,
143 using this BNF syntax:
144 @code
145 chunk-ext = *( ";" chunk-ext-name [ "=" chunk-ext-val ] )
146 chunk-ext-name = token
147 chunk-ext-val = token / quoted-string
148 @endcode
149 The data pointed to by this string view must remain
150 valid for the lifetime of any operations performed on
151 the object.
152
153 @see https://tools.ietf.org/html/rfc7230#section-4.1.1
154 */
155 chunk_header(
156 std::size_t size,
157 string_view extensions);
158
159 /** Constructor
160
161 This constructs a buffer sequence representing a
162 @em chunked-body size and terminating CRLF (`"\r\n"`)
163 with provided chunk extensions.
164 The default allocator is used to provide storage for the
165 extensions object.
166
167 @param size The size of the chunk body that follows.
168 The value must be greater than zero.
169
170 @param extensions The chunk extensions object. The expression
171 `extensions.str()` must be valid, and the return type must
172 be convertible to @ref string_view. This object will be copied
173 or moved as needed to ensure that the chunk header object retains
174 ownership of the buffers provided by the chunk extensions object.
175
176 @note This function participates in overload resolution only
177 if @b ChunkExtensions meets the requirements stated above.
178
179 @see https://tools.ietf.org/html/rfc7230#section-4.1
180 */
181 template<class ChunkExtensions
182#if ! BOOST_BEAST_DOXYGEN
183 , class = typename std::enable_if<
184 detail::is_chunk_extensions<
185 ChunkExtensions>::value>::type
186#endif
187 >
188 chunk_header(
189 std::size_t size,
190 ChunkExtensions&& extensions);
191
192 /** Constructor
193
194 This constructs a buffer sequence representing a
195 @em chunked-body size and terminating CRLF (`"\r\n"`)
196 with provided chunk extensions.
197 The specified allocator is used to provide storage for the
198 extensions object.
199
200 @param size The size of the chunk body that follows.
201 The value be greater than zero.
202
203 @param extensions The chunk extensions object. The expression
204 `extensions.str()` must be valid, and the return type must
205 be convertible to @ref string_view. This object will be copied
206 or moved as needed to ensure that the chunk header object retains
207 ownership of the buffers provided by the chunk extensions object.
208
209 @param allocator The allocator to provide storage for the moved
210 or copied extensions object.
211
212 @note This function participates in overload resolution only
213 if @b ChunkExtensions meets the requirements stated above.
214
215 @see https://tools.ietf.org/html/rfc7230#section-4.1
216 */
217 template<class ChunkExtensions, class Allocator
218#if ! BOOST_BEAST_DOXYGEN
219 , class = typename std::enable_if<
220 detail::is_chunk_extensions<
221 ChunkExtensions>::value>::type
222#endif
223 >
224 chunk_header(
225 std::size_t size,
226 ChunkExtensions&& extensions,
227 Allocator const& allocator);
228
229 //-----
230
92f5a8d4 231 /// Required for <em>ConstBufferSequence</em>
b32b8144 232#if BOOST_BEAST_DOXYGEN
92f5a8d4 233 using value_type = __implementation_defined__;
b32b8144
FG
234#else
235 using value_type = typename view_type::value_type;
236#endif
237
92f5a8d4 238 /// Required for <em>ConstBufferSequence</em>
b32b8144 239#if BOOST_BEAST_DOXYGEN
92f5a8d4 240 using const_iterator = __implementation_defined__;
b32b8144
FG
241#else
242 using const_iterator = typename view_type::const_iterator;
243#endif
244
92f5a8d4 245 /// Required for <em>ConstBufferSequence</em>
b32b8144
FG
246 chunk_header(chunk_header const&) = default;
247
92f5a8d4 248 /// Required for <em>ConstBufferSequence</em>
b32b8144
FG
249 const_iterator
250 begin() const
251 {
252 return view_.begin();
253 }
254
92f5a8d4 255 /// Required for <em>ConstBufferSequence</em>
b32b8144
FG
256 const_iterator
257 end() const
258 {
259 return view_.end();
260 }
261};
262
263//------------------------------------------------------------------------------
264
265/** A @em chunk
266
92f5a8d4 267 This implements a <em>ConstBufferSequence</em> representing
b32b8144
FG
268 a @em chunk. The serialized format is as follows:
269 @code
270 chunk = chunk-size [ chunk-ext ] CRLF chunk-data CRLF
271 chunk-size = 1*HEXDIG
272 chunk-ext = *( ";" chunk-ext-name [ "=" chunk-ext-val ] )
273 chunk-ext-name = token
274 chunk-ext-val = token / quoted-string
275 chunk-data = 1*OCTET ; a sequence of chunk-size octets
276 @endcode
277 The chunk extension is optional.
278
279 To use this class, pass an instance of it to a
280 stream algorithm as the buffer sequence.
281
282 @see https://tools.ietf.org/html/rfc7230#section-4.1
283*/
284template<class ConstBufferSequence>
285class chunk_body
286{
287 using view_type = buffers_cat_view<
288 detail::chunk_size, // chunk-size
92f5a8d4 289 net::const_buffer, // chunk-extensions
b32b8144
FG
290 chunk_crlf, // CRLF
291 ConstBufferSequence, // chunk-body
292 chunk_crlf>; // CRLF
293
294 std::shared_ptr<
295 detail::chunk_extensions> exts_;
296 view_type view_;
297
298public:
299 /** Constructor
300
301 This constructs buffers representing a complete @em chunk
302 with no chunk extensions and having the size and contents
303 of the specified buffer sequence.
304
305 @param buffers A buffer sequence representing the chunk
306 body. Although the buffers object may be copied as necessary,
307 ownership of the underlying memory blocks is retained by the
308 caller, which must guarantee that they remain valid while this
309 object is in use.
310
311 @see https://tools.ietf.org/html/rfc7230#section-4.1
312 */
313 explicit
314 chunk_body(
315 ConstBufferSequence const& buffers);
316
317 /** Constructor
318
319 This constructs buffers representing a complete @em chunk
320 with the passed chunk extensions and having the size and
321 contents of the specified buffer sequence.
322
323 @param buffers A buffer sequence representing the chunk
324 body. Although the buffers object may be copied as necessary,
325 ownership of the underlying memory blocks is retained by the
326 caller, which must guarantee that they remain valid while this
327 object is in use.
328
329 @param extensions The chunk extensions string. This
330 string must be formatted correctly as per rfc7230,
331 using this BNF syntax:
332 @code
333 chunk-ext = *( ";" chunk-ext-name [ "=" chunk-ext-val ] )
334 chunk-ext-name = token
335 chunk-ext-val = token / quoted-string
336 @endcode
337 The data pointed to by this string view must remain
338 valid for the lifetime of any operations performed on
339 the object.
340
341 @see https://tools.ietf.org/html/rfc7230#section-4.1.1
342 */
343 chunk_body(
344 ConstBufferSequence const& buffers,
345 string_view extensions);
346
347 /** Constructor
348
349 This constructs buffers representing a complete @em chunk
350 with the passed chunk extensions and having the size and
351 contents of the specified buffer sequence.
352 The default allocator is used to provide storage for the
353 extensions object.
354
355 @param buffers A buffer sequence representing the chunk
356 body. Although the buffers object may be copied as necessary,
357 ownership of the underlying memory blocks is retained by the
358 caller, which must guarantee that they remain valid while this
359 object is in use.
360
361 @param extensions The chunk extensions object. The expression
362 `extensions.str()` must be valid, and the return type must
363 be convertible to @ref string_view. This object will be copied
364 or moved as needed to ensure that the chunk header object retains
365 ownership of the buffers provided by the chunk extensions object.
366
367 @note This function participates in overload resolution only
368 if @b ChunkExtensions meets the requirements stated above.
369
370 @see https://tools.ietf.org/html/rfc7230#section-4.1
371 */
372 template<class ChunkExtensions
373#if ! BOOST_BEAST_DOXYGEN
374 , class = typename std::enable_if<
375 ! std::is_convertible<typename std::decay<
376 ChunkExtensions>::type, string_view>::value>::type
377#endif
378 >
379 chunk_body(
380 ConstBufferSequence const& buffers,
381 ChunkExtensions&& extensions);
382
383 /** Constructor
384
385 This constructs buffers representing a complete @em chunk
386 with the passed chunk extensions and having the size and
387 contents of the specified buffer sequence.
388 The specified allocator is used to provide storage for the
389 extensions object.
390
391 @param buffers A buffer sequence representing the chunk
392 body. Although the buffers object may be copied as necessary,
393 ownership of the underlying memory blocks is retained by the
394 caller, which must guarantee that they remain valid while this
395 object is in use.
396
397 @param extensions The chunk extensions object. The expression
398 `extensions.str()` must be valid, and the return type must
399 be convertible to @ref string_view. This object will be copied
400 or moved as needed to ensure that the chunk header object retains
401 ownership of the buffers provided by the chunk extensions object.
402
403 @param allocator The allocator to provide storage for the moved
404 or copied extensions object.
405
406 @note This function participates in overload resolution only
407 if @b ChunkExtensions meets the requirements stated above.
408
409 @see https://tools.ietf.org/html/rfc7230#section-4.1
410 */
411 template<class ChunkExtensions, class Allocator
412#if ! BOOST_BEAST_DOXYGEN
413 , class = typename std::enable_if<
414 ! std::is_convertible<typename std::decay<
415 ChunkExtensions>::type, string_view>::value>::type
416#endif
417 >
418 chunk_body(
419 ConstBufferSequence const& buffers,
420 ChunkExtensions&& extensions,
421 Allocator const& allocator);
422
423 //-----
424
92f5a8d4 425 /// Required for <em>ConstBufferSequence</em>
b32b8144 426#if BOOST_BEAST_DOXYGEN
92f5a8d4 427 using value_type = __implementation_defined__;
b32b8144
FG
428#else
429 using value_type = typename view_type::value_type;
430#endif
431
92f5a8d4 432 /// Required for <em>ConstBufferSequence</em>
b32b8144 433#if BOOST_BEAST_DOXYGEN
92f5a8d4 434 using const_iterator = __implementation_defined__;
b32b8144
FG
435#else
436 using const_iterator = typename view_type::const_iterator;
437#endif
438
92f5a8d4 439 /// Required for <em>ConstBufferSequence</em>
b32b8144
FG
440 const_iterator
441 begin() const
442 {
443 return view_.begin();
444 }
445
92f5a8d4 446 /// Required for <em>ConstBufferSequence</em>
b32b8144
FG
447 const_iterator
448 end() const
449 {
450 return view_.end();
451 }
452};
453
454//------------------------------------------------------------------------------
455
456/** A chunked-encoding last chunk
457*/
458template<class Trailer = chunk_crlf>
459class chunk_last
460{
461 static_assert(
462 is_fields<Trailer>::value ||
92f5a8d4 463 net::is_const_buffer_sequence<Trailer>::value,
b32b8144
FG
464 "Trailer requirements not met");
465
466 using buffers_type = typename
467 detail::buffers_or_fields<Trailer>::type;
468
469 using view_type =
470 buffers_cat_view<
471 detail::chunk_size0, // "0\r\n"
472 buffers_type>; // Trailer (includes CRLF)
473
474 template<class Allocator>
475 buffers_type
476 prepare(Trailer const& trailer, Allocator const& alloc);
477
478 buffers_type
479 prepare(Trailer const& trailer, std::true_type);
480
481 buffers_type
482 prepare(Trailer const& trailer, std::false_type);
483
484 std::shared_ptr<void> sp_;
485 view_type view_;
486
487public:
488 /** Constructor
489
490 The last chunk will have an empty trailer
491 */
492 chunk_last();
493
494 /** Constructor
495
496 @param trailer The trailer to use. This may be
497 a type meeting the requirements of either Fields
498 or ConstBufferSequence. If it is a ConstBufferSequence,
499 the trailer must be formatted correctly as per rfc7230
500 including a CRLF on its own line to denote the end
501 of the trailer.
502 */
503 explicit
504 chunk_last(Trailer const& trailer);
505
506 /** Constructor
507
508 @param trailer The trailer to use. This type must
509 meet the requirements of Fields.
510
511 @param allocator The allocator to use for storing temporary
512 data associated with the serialized trailer buffers.
513 */
514#if BOOST_BEAST_DOXYGEN
515 template<class Allocator>
516 chunk_last(Trailer const& trailer, Allocator const& allocator);
517#else
518 template<class DeducedTrailer, class Allocator,
519 class = typename std::enable_if<
520 is_fields<DeducedTrailer>::value>::type>
521 chunk_last(
522 DeducedTrailer const& trailer, Allocator const& allocator);
523#endif
524
525 //-----
526
92f5a8d4 527 /// Required for <em>ConstBufferSequence</em>
b32b8144
FG
528 chunk_last(chunk_last const&) = default;
529
92f5a8d4 530 /// Required for <em>ConstBufferSequence</em>
b32b8144 531#if BOOST_BEAST_DOXYGEN
92f5a8d4 532 using value_type = __implementation_defined__;
b32b8144
FG
533#else
534 using value_type =
535 typename view_type::value_type;
536#endif
537
92f5a8d4 538 /// Required for <em>ConstBufferSequence</em>
b32b8144 539#if BOOST_BEAST_DOXYGEN
92f5a8d4 540 using const_iterator = __implementation_defined__;
b32b8144
FG
541#else
542 using const_iterator =
543 typename view_type::const_iterator;
544#endif
545
92f5a8d4 546 /// Required for <em>ConstBufferSequence</em>
b32b8144
FG
547 const_iterator
548 begin() const
549 {
550 return view_.begin();
551 }
552
92f5a8d4 553 /// Required for <em>ConstBufferSequence</em>
b32b8144
FG
554 const_iterator
555 end() const
556 {
557 return view_.end();
558 }
559};
560
561//------------------------------------------------------------------------------
562
563/** A set of chunk extensions
564
565 This container stores a set of chunk extensions suited for use with
566 @ref chunk_header and @ref chunk_body. The container may be iterated
567 to access the extensions in their structured form.
568
569 Meets the requirements of ChunkExtensions
570*/
571template<class Allocator>
572class basic_chunk_extensions
573{
574 std::basic_string<char,
575 std::char_traits<char>, Allocator> s_;
576
577 std::basic_string<char,
578 std::char_traits<char>, Allocator> range_;
579
580 template<class FwdIt>
581 FwdIt
582 do_parse(FwdIt it, FwdIt last, error_code& ec);
583
584 void
585 do_insert(string_view name, string_view value);
586
587public:
588 /** The type of value when iterating.
589
590 The first element of the pair is the name, and the second
591 element is the value which may be empty. The value is
592 stored in its raw representation, without quotes or escapes.
593 */
594 using value_type = std::pair<string_view, string_view>;
595
596 class const_iterator;
597
598 /// Constructor
599 basic_chunk_extensions() = default;
600
601 /// Constructor
602 basic_chunk_extensions(basic_chunk_extensions&&) = default;
603
604 /// Constructor
605 basic_chunk_extensions(basic_chunk_extensions const&) = default;
606
607 /** Constructor
608
609 @param allocator The allocator to use for storing the serialized extension
610 */
611 explicit
612 basic_chunk_extensions(Allocator const& allocator)
613 : s_(allocator)
614 {
615 }
616
617 /** Clear the chunk extensions
618
619 This preserves the capacity of the internal string
620 used to hold the serialized representation.
621 */
622 void
623 clear()
624 {
625 s_.clear();
626 }
627
628 /** Parse a set of chunk extensions
629
630 Any previous extensions will be cleared
631 */
632 void
633 parse(string_view s, error_code& ec);
634
635 /** Insert an extension name with an empty value
636
637 @param name The name of the extension
638 */
639 void
640 insert(string_view name);
641
642 /** Insert an extension value
643
644 @param name The name of the extension
645
646 @param value The value to insert. Depending on the
647 contents, the serialized extension may use a quoted string.
648 */
649 void
650 insert(string_view name, string_view value);
651
652 /// Return the serialized representation of the chunk extension
653 string_view
654 str() const
655 {
656 return s_;
657 }
658
659 const_iterator
660 begin() const;
661
662 const_iterator
663 end() const;
664};
665
666//------------------------------------------------------------------------------
667
668/// A set of chunk extensions
669using chunk_extensions =
670 basic_chunk_extensions<std::allocator<char>>;
671
672/** Returns a @ref chunk_body
673
674 This functions constructs and returns a complete
675 @ref chunk_body for a chunk body represented by the
676 specified buffer sequence.
677
678 @param buffers The buffers representing the chunk body.
679
680 @param args Optional arguments passed to the @ref chunk_body constructor.
681
682 @note This function is provided as a notational convenience
683 to omit specification of the class template arguments.
684*/
685template<class ConstBufferSequence, class... Args>
686auto
687make_chunk(
688 ConstBufferSequence const& buffers,
689 Args&&... args) ->
690 chunk_body<ConstBufferSequence>
691{
692 return chunk_body<ConstBufferSequence>(
693 buffers, std::forward<Args>(args)...);
694}
695
696/** Returns a @ref chunk_last
697
698 @note This function is provided as a notational convenience
699 to omit specification of the class template arguments.
700*/
701inline
702chunk_last<chunk_crlf>
703make_chunk_last()
704{
705 return chunk_last<chunk_crlf>{};
706}
707
708/** Returns a @ref chunk_last
709
710 This function construct and returns a complete
711 @ref chunk_last for a last chunk containing the
712 specified trailers.
713
714 @param trailer A ConstBufferSequence or
715 @note This function is provided as a notational convenience
716 to omit specification of the class template arguments.
717
718 @param args Optional arguments passed to the @ref chunk_last
719 constructor.
720*/
721template<class Trailer, class... Args>
722chunk_last<Trailer>
723make_chunk_last(
724 Trailer const& trailer,
725 Args&&... args)
726{
727 return chunk_last<Trailer>{
728 trailer, std::forward<Args>(args)...};
729}
730
731} // http
732} // beast
733} // boost
734
92f5a8d4 735#include <boost/beast/http/impl/chunk_encode.hpp>
b32b8144
FG
736
737#endif