|
||||
File indexing completed on 2025-01-18 09:29:31
0001 // 0002 // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) 0003 // 0004 // Distributed under the Boost Software License, Version 1.0. (See accompanying 0005 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 0006 // 0007 // Official repository: https://github.com/boostorg/beast 0008 // 0009 0010 #ifndef BOOST_BEAST_HTTP_CHUNK_ENCODE_HPP 0011 #define BOOST_BEAST_HTTP_CHUNK_ENCODE_HPP 0012 0013 #include <boost/beast/core/detail/config.hpp> 0014 #include <boost/beast/core/buffers_cat.hpp> 0015 #include <boost/beast/core/string.hpp> 0016 #include <boost/beast/http/type_traits.hpp> 0017 #include <boost/beast/http/detail/chunk_encode.hpp> 0018 #include <boost/asio/buffer.hpp> 0019 #include <memory> 0020 #include <type_traits> 0021 0022 namespace boost { 0023 namespace beast { 0024 namespace http { 0025 0026 /** A chunked encoding crlf 0027 0028 This implements a <em>ConstBufferSequence</em> holding the CRLF 0029 (`"\r\n"`) used as a delimiter in a @em chunk. 0030 0031 To use this class, pass an instance of it to a 0032 stream algorithm as the buffer sequence: 0033 @code 0034 // writes "\r\n" 0035 net::write(stream, chunk_crlf{}); 0036 @endcode 0037 0038 @see https://tools.ietf.org/html/rfc7230#section-4.1 0039 */ 0040 struct chunk_crlf 0041 { 0042 /// Constructor 0043 chunk_crlf() = default; 0044 0045 //----- 0046 0047 /// Required for <em>ConstBufferSequence</em> 0048 #if BOOST_BEAST_DOXYGEN 0049 using value_type = __implementation_defined__; 0050 #else 0051 using value_type = net::const_buffer; 0052 #endif 0053 0054 /// Required for <em>ConstBufferSequence</em> 0055 using const_iterator = value_type const*; 0056 0057 /// Required for <em>ConstBufferSequence</em> 0058 chunk_crlf(chunk_crlf const&) = default; 0059 0060 /// Required for <em>ConstBufferSequence</em> 0061 const_iterator 0062 begin() const 0063 { 0064 static net::const_buffer const cb{"\r\n", 2}; 0065 return &cb; 0066 } 0067 0068 /// Required for <em>ConstBufferSequence</em> 0069 const_iterator 0070 end() const 0071 { 0072 return begin() + 1; 0073 } 0074 }; 0075 0076 //------------------------------------------------------------------------------ 0077 0078 /** A @em chunk header 0079 0080 This implements a <em>ConstBufferSequence</em> representing the 0081 header of a @em chunk. The serialized format is as follows: 0082 @code 0083 chunk-header = 1*HEXDIG chunk-ext CRLF 0084 chunk-ext = *( ";" chunk-ext-name [ "=" chunk-ext-val ] ) 0085 chunk-ext-name = token 0086 chunk-ext-val = token / quoted-string 0087 @endcode 0088 The chunk extension is optional. After the header and 0089 chunk body have been serialized, it is the callers 0090 responsibility to also serialize the final CRLF (`"\r\n"`). 0091 0092 This class allows the caller to emit piecewise chunk bodies, 0093 by first serializing the chunk header using this class and then 0094 serializing the chunk body in a series of one or more calls to 0095 a stream write operation. 0096 0097 To use this class, pass an instance of it to a 0098 stream algorithm as the buffer sequence: 0099 @code 0100 // writes "400;x\r\n" 0101 net::write(stream, chunk_header{1024, "x"}); 0102 @endcode 0103 0104 @see https://tools.ietf.org/html/rfc7230#section-4.1 0105 */ 0106 class chunk_header 0107 { 0108 using view_type = buffers_cat_view< 0109 detail::chunk_size, // chunk-size 0110 net::const_buffer, // chunk-extensions 0111 chunk_crlf>; // CRLF 0112 0113 std::shared_ptr< 0114 detail::chunk_extensions> exts_; 0115 view_type view_; 0116 0117 public: 0118 /** Constructor 0119 0120 This constructs a buffer sequence representing a 0121 @em chunked-body size and terminating CRLF (`"\r\n"`) 0122 with no chunk extensions. 0123 0124 @param size The size of the chunk body that follows. 0125 The value must be greater than zero. 0126 0127 @see https://tools.ietf.org/html/rfc7230#section-4.1 0128 */ 0129 explicit 0130 chunk_header(std::size_t size); 0131 0132 /** Constructor 0133 0134 This constructs a buffer sequence representing a 0135 @em chunked-body size and terminating CRLF (`"\r\n"`) 0136 with provided chunk extensions. 0137 0138 @param size The size of the chunk body that follows. 0139 The value must be greater than zero. 0140 0141 @param extensions The chunk extensions string. This 0142 string must be formatted correctly as per rfc7230, 0143 using this BNF syntax: 0144 @code 0145 chunk-ext = *( ";" chunk-ext-name [ "=" chunk-ext-val ] ) 0146 chunk-ext-name = token 0147 chunk-ext-val = token / quoted-string 0148 @endcode 0149 The data pointed to by this string view must remain 0150 valid for the lifetime of any operations performed on 0151 the object. 0152 0153 @see https://tools.ietf.org/html/rfc7230#section-4.1.1 0154 */ 0155 chunk_header( 0156 std::size_t size, 0157 string_view extensions); 0158 0159 /** Constructor 0160 0161 This constructs a buffer sequence representing a 0162 @em chunked-body size and terminating CRLF (`"\r\n"`) 0163 with provided chunk extensions. 0164 The default allocator is used to provide storage for the 0165 extensions object. 0166 0167 @param size The size of the chunk body that follows. 0168 The value must be greater than zero. 0169 0170 @param extensions The chunk extensions object. The expression 0171 `extensions.str()` must be valid, and the return type must 0172 be convertible to @ref string_view. This object will be copied 0173 or moved as needed to ensure that the chunk header object retains 0174 ownership of the buffers provided by the chunk extensions object. 0175 0176 @note This function participates in overload resolution only 0177 if @b ChunkExtensions meets the requirements stated above. 0178 0179 @see https://tools.ietf.org/html/rfc7230#section-4.1 0180 */ 0181 template<class ChunkExtensions 0182 #if ! BOOST_BEAST_DOXYGEN 0183 , class = typename std::enable_if< 0184 detail::is_chunk_extensions< 0185 ChunkExtensions>::value>::type 0186 #endif 0187 > 0188 chunk_header( 0189 std::size_t size, 0190 ChunkExtensions&& extensions); 0191 0192 /** Constructor 0193 0194 This constructs a buffer sequence representing a 0195 @em chunked-body size and terminating CRLF (`"\r\n"`) 0196 with provided chunk extensions. 0197 The specified allocator is used to provide storage for the 0198 extensions object. 0199 0200 @param size The size of the chunk body that follows. 0201 The value be greater than zero. 0202 0203 @param extensions The chunk extensions object. The expression 0204 `extensions.str()` must be valid, and the return type must 0205 be convertible to @ref string_view. This object will be copied 0206 or moved as needed to ensure that the chunk header object retains 0207 ownership of the buffers provided by the chunk extensions object. 0208 0209 @param allocator The allocator to provide storage for the moved 0210 or copied extensions object. 0211 0212 @note This function participates in overload resolution only 0213 if @b ChunkExtensions meets the requirements stated above. 0214 0215 @see https://tools.ietf.org/html/rfc7230#section-4.1 0216 */ 0217 template<class ChunkExtensions, class Allocator 0218 #if ! BOOST_BEAST_DOXYGEN 0219 , class = typename std::enable_if< 0220 detail::is_chunk_extensions< 0221 ChunkExtensions>::value>::type 0222 #endif 0223 > 0224 chunk_header( 0225 std::size_t size, 0226 ChunkExtensions&& extensions, 0227 Allocator const& allocator); 0228 0229 //----- 0230 0231 /// Required for <em>ConstBufferSequence</em> 0232 #if BOOST_BEAST_DOXYGEN 0233 using value_type = __implementation_defined__; 0234 #else 0235 using value_type = typename view_type::value_type; 0236 #endif 0237 0238 /// Required for <em>ConstBufferSequence</em> 0239 #if BOOST_BEAST_DOXYGEN 0240 using const_iterator = __implementation_defined__; 0241 #else 0242 using const_iterator = typename view_type::const_iterator; 0243 #endif 0244 0245 /// Required for <em>ConstBufferSequence</em> 0246 chunk_header(chunk_header const&) = default; 0247 0248 /// Required for <em>ConstBufferSequence</em> 0249 const_iterator 0250 begin() const 0251 { 0252 return view_.begin(); 0253 } 0254 0255 /// Required for <em>ConstBufferSequence</em> 0256 const_iterator 0257 end() const 0258 { 0259 return view_.end(); 0260 } 0261 }; 0262 0263 //------------------------------------------------------------------------------ 0264 0265 /** A @em chunk 0266 0267 This implements a <em>ConstBufferSequence</em> representing 0268 a @em chunk. The serialized format is as follows: 0269 @code 0270 chunk = chunk-size [ chunk-ext ] CRLF chunk-data CRLF 0271 chunk-size = 1*HEXDIG 0272 chunk-ext = *( ";" chunk-ext-name [ "=" chunk-ext-val ] ) 0273 chunk-ext-name = token 0274 chunk-ext-val = token / quoted-string 0275 chunk-data = 1*OCTET ; a sequence of chunk-size octets 0276 @endcode 0277 The chunk extension is optional. 0278 0279 To use this class, pass an instance of it to a 0280 stream algorithm as the buffer sequence. 0281 0282 @see https://tools.ietf.org/html/rfc7230#section-4.1 0283 */ 0284 template<class ConstBufferSequence> 0285 class chunk_body 0286 { 0287 using view_type = buffers_cat_view< 0288 detail::chunk_size, // chunk-size 0289 net::const_buffer, // chunk-extensions 0290 chunk_crlf, // CRLF 0291 ConstBufferSequence, // chunk-body 0292 chunk_crlf>; // CRLF 0293 0294 std::shared_ptr< 0295 detail::chunk_extensions> exts_; 0296 view_type view_; 0297 0298 public: 0299 /** Constructor 0300 0301 This constructs buffers representing a complete @em chunk 0302 with no chunk extensions and having the size and contents 0303 of the specified buffer sequence. 0304 0305 @param buffers A buffer sequence representing the chunk 0306 body. Although the buffers object may be copied as necessary, 0307 ownership of the underlying memory blocks is retained by the 0308 caller, which must guarantee that they remain valid while this 0309 object is in use. 0310 0311 @see https://tools.ietf.org/html/rfc7230#section-4.1 0312 */ 0313 explicit 0314 chunk_body( 0315 ConstBufferSequence const& buffers); 0316 0317 /** Constructor 0318 0319 This constructs buffers representing a complete @em chunk 0320 with the passed chunk extensions and having the size and 0321 contents of the specified buffer sequence. 0322 0323 @param buffers A buffer sequence representing the chunk 0324 body. Although the buffers object may be copied as necessary, 0325 ownership of the underlying memory blocks is retained by the 0326 caller, which must guarantee that they remain valid while this 0327 object is in use. 0328 0329 @param extensions The chunk extensions string. This 0330 string must be formatted correctly as per rfc7230, 0331 using this BNF syntax: 0332 @code 0333 chunk-ext = *( ";" chunk-ext-name [ "=" chunk-ext-val ] ) 0334 chunk-ext-name = token 0335 chunk-ext-val = token / quoted-string 0336 @endcode 0337 The data pointed to by this string view must remain 0338 valid for the lifetime of any operations performed on 0339 the object. 0340 0341 @see https://tools.ietf.org/html/rfc7230#section-4.1.1 0342 */ 0343 chunk_body( 0344 ConstBufferSequence const& buffers, 0345 string_view extensions); 0346 0347 /** Constructor 0348 0349 This constructs buffers representing a complete @em chunk 0350 with the passed chunk extensions and having the size and 0351 contents of the specified buffer sequence. 0352 The default allocator is used to provide storage for the 0353 extensions object. 0354 0355 @param buffers A buffer sequence representing the chunk 0356 body. Although the buffers object may be copied as necessary, 0357 ownership of the underlying memory blocks is retained by the 0358 caller, which must guarantee that they remain valid while this 0359 object is in use. 0360 0361 @param extensions The chunk extensions object. The expression 0362 `extensions.str()` must be valid, and the return type must 0363 be convertible to @ref string_view. This object will be copied 0364 or moved as needed to ensure that the chunk header object retains 0365 ownership of the buffers provided by the chunk extensions object. 0366 0367 @note This function participates in overload resolution only 0368 if @b ChunkExtensions meets the requirements stated above. 0369 0370 @see https://tools.ietf.org/html/rfc7230#section-4.1 0371 */ 0372 template<class ChunkExtensions 0373 #if ! BOOST_BEAST_DOXYGEN 0374 , class = typename std::enable_if< 0375 ! std::is_convertible<typename std::decay< 0376 ChunkExtensions>::type, string_view>::value>::type 0377 #endif 0378 > 0379 chunk_body( 0380 ConstBufferSequence const& buffers, 0381 ChunkExtensions&& extensions); 0382 0383 /** Constructor 0384 0385 This constructs buffers representing a complete @em chunk 0386 with the passed chunk extensions and having the size and 0387 contents of the specified buffer sequence. 0388 The specified allocator is used to provide storage for the 0389 extensions object. 0390 0391 @param buffers A buffer sequence representing the chunk 0392 body. Although the buffers object may be copied as necessary, 0393 ownership of the underlying memory blocks is retained by the 0394 caller, which must guarantee that they remain valid while this 0395 object is in use. 0396 0397 @param extensions The chunk extensions object. The expression 0398 `extensions.str()` must be valid, and the return type must 0399 be convertible to @ref string_view. This object will be copied 0400 or moved as needed to ensure that the chunk header object retains 0401 ownership of the buffers provided by the chunk extensions object. 0402 0403 @param allocator The allocator to provide storage for the moved 0404 or copied extensions object. 0405 0406 @note This function participates in overload resolution only 0407 if @b ChunkExtensions meets the requirements stated above. 0408 0409 @see https://tools.ietf.org/html/rfc7230#section-4.1 0410 */ 0411 template<class ChunkExtensions, class Allocator 0412 #if ! BOOST_BEAST_DOXYGEN 0413 , class = typename std::enable_if< 0414 ! std::is_convertible<typename std::decay< 0415 ChunkExtensions>::type, string_view>::value>::type 0416 #endif 0417 > 0418 chunk_body( 0419 ConstBufferSequence const& buffers, 0420 ChunkExtensions&& extensions, 0421 Allocator const& allocator); 0422 0423 //----- 0424 0425 /// Required for <em>ConstBufferSequence</em> 0426 #if BOOST_BEAST_DOXYGEN 0427 using value_type = __implementation_defined__; 0428 #else 0429 using value_type = typename view_type::value_type; 0430 #endif 0431 0432 /// Required for <em>ConstBufferSequence</em> 0433 #if BOOST_BEAST_DOXYGEN 0434 using const_iterator = __implementation_defined__; 0435 #else 0436 using const_iterator = typename view_type::const_iterator; 0437 #endif 0438 0439 /// Required for <em>ConstBufferSequence</em> 0440 const_iterator 0441 begin() const 0442 { 0443 return view_.begin(); 0444 } 0445 0446 /// Required for <em>ConstBufferSequence</em> 0447 const_iterator 0448 end() const 0449 { 0450 return view_.end(); 0451 } 0452 }; 0453 0454 //------------------------------------------------------------------------------ 0455 0456 /** A chunked-encoding last chunk 0457 */ 0458 template<class Trailer = chunk_crlf> 0459 class chunk_last 0460 { 0461 static_assert( 0462 is_fields<Trailer>::value || 0463 net::is_const_buffer_sequence<Trailer>::value, 0464 "Trailer requirements not met"); 0465 0466 using buffers_type = typename 0467 detail::buffers_or_fields<Trailer>::type; 0468 0469 using view_type = 0470 buffers_cat_view< 0471 detail::chunk_size0, // "0\r\n" 0472 buffers_type>; // Trailer (includes CRLF) 0473 0474 template<class Allocator> 0475 buffers_type 0476 prepare(Trailer const& trailer, Allocator const& alloc); 0477 0478 buffers_type 0479 prepare(Trailer const& trailer, std::true_type); 0480 0481 buffers_type 0482 prepare(Trailer const& trailer, std::false_type); 0483 0484 std::shared_ptr<void> sp_; 0485 view_type view_; 0486 0487 public: 0488 /** Constructor 0489 0490 The last chunk will have an empty trailer 0491 */ 0492 chunk_last(); 0493 0494 /** Constructor 0495 0496 @param trailer The trailer to use. This may be 0497 a type meeting the requirements of either Fields 0498 or ConstBufferSequence. If it is a ConstBufferSequence, 0499 the trailer must be formatted correctly as per rfc7230 0500 including a CRLF on its own line to denote the end 0501 of the trailer. 0502 */ 0503 explicit 0504 chunk_last(Trailer const& trailer); 0505 0506 /** Constructor 0507 0508 @param trailer The trailer to use. This type must 0509 meet the requirements of Fields. 0510 0511 @param allocator The allocator to use for storing temporary 0512 data associated with the serialized trailer buffers. 0513 */ 0514 #if BOOST_BEAST_DOXYGEN 0515 template<class Allocator> 0516 chunk_last(Trailer const& trailer, Allocator const& allocator); 0517 #else 0518 template<class DeducedTrailer, class Allocator, 0519 class = typename std::enable_if< 0520 is_fields<DeducedTrailer>::value>::type> 0521 chunk_last( 0522 DeducedTrailer const& trailer, Allocator const& allocator); 0523 #endif 0524 0525 //----- 0526 0527 /// Required for <em>ConstBufferSequence</em> 0528 chunk_last(chunk_last const&) = default; 0529 0530 /// Required for <em>ConstBufferSequence</em> 0531 #if BOOST_BEAST_DOXYGEN 0532 using value_type = __implementation_defined__; 0533 #else 0534 using value_type = 0535 typename view_type::value_type; 0536 #endif 0537 0538 /// Required for <em>ConstBufferSequence</em> 0539 #if BOOST_BEAST_DOXYGEN 0540 using const_iterator = __implementation_defined__; 0541 #else 0542 using const_iterator = 0543 typename view_type::const_iterator; 0544 #endif 0545 0546 /// Required for <em>ConstBufferSequence</em> 0547 const_iterator 0548 begin() const 0549 { 0550 return view_.begin(); 0551 } 0552 0553 /// Required for <em>ConstBufferSequence</em> 0554 const_iterator 0555 end() const 0556 { 0557 return view_.end(); 0558 } 0559 }; 0560 0561 //------------------------------------------------------------------------------ 0562 0563 /** A set of chunk extensions 0564 0565 This container stores a set of chunk extensions suited for use with 0566 @ref chunk_header and @ref chunk_body. The container may be iterated 0567 to access the extensions in their structured form. 0568 0569 Meets the requirements of ChunkExtensions 0570 */ 0571 template<class Allocator> 0572 class basic_chunk_extensions 0573 { 0574 std::basic_string<char, 0575 std::char_traits<char>, Allocator> s_; 0576 0577 std::basic_string<char, 0578 std::char_traits<char>, Allocator> range_; 0579 0580 template<class FwdIt> 0581 FwdIt 0582 do_parse(FwdIt it, FwdIt last, error_code& ec); 0583 0584 void 0585 do_insert(string_view name, string_view value); 0586 0587 public: 0588 /** The type of value when iterating. 0589 0590 The first element of the pair is the name, and the second 0591 element is the value which may be empty. The value is 0592 stored in its raw representation, without quotes or escapes. 0593 */ 0594 using value_type = std::pair<string_view, string_view>; 0595 0596 class const_iterator; 0597 0598 /// Constructor 0599 basic_chunk_extensions() = default; 0600 0601 /// Constructor 0602 basic_chunk_extensions(basic_chunk_extensions&&) = default; 0603 0604 /// Constructor 0605 basic_chunk_extensions(basic_chunk_extensions const&) = default; 0606 0607 /** Constructor 0608 0609 @param allocator The allocator to use for storing the serialized extension 0610 */ 0611 explicit 0612 basic_chunk_extensions(Allocator const& allocator) 0613 : s_(allocator) 0614 { 0615 } 0616 0617 /** Clear the chunk extensions 0618 0619 This preserves the capacity of the internal string 0620 used to hold the serialized representation. 0621 */ 0622 void 0623 clear() 0624 { 0625 s_.clear(); 0626 } 0627 0628 /** Parse a set of chunk extensions 0629 0630 Any previous extensions will be cleared 0631 */ 0632 void 0633 parse(string_view s, error_code& ec); 0634 0635 /** Insert an extension name with an empty value 0636 0637 @param name The name of the extension 0638 */ 0639 void 0640 insert(string_view name); 0641 0642 /** Insert an extension value 0643 0644 @param name The name of the extension 0645 0646 @param value The value to insert. Depending on the 0647 contents, the serialized extension may use a quoted string. 0648 */ 0649 void 0650 insert(string_view name, string_view value); 0651 0652 /// Return the serialized representation of the chunk extension 0653 string_view 0654 str() const 0655 { 0656 return s_; 0657 } 0658 0659 const_iterator 0660 begin() const; 0661 0662 const_iterator 0663 end() const; 0664 }; 0665 0666 //------------------------------------------------------------------------------ 0667 0668 /// A set of chunk extensions 0669 using chunk_extensions = 0670 basic_chunk_extensions<std::allocator<char>>; 0671 0672 /** Returns a @ref chunk_body 0673 0674 This functions constructs and returns a complete 0675 @ref chunk_body for a chunk body represented by the 0676 specified buffer sequence. 0677 0678 @param buffers The buffers representing the chunk body. 0679 0680 @param args Optional arguments passed to the @ref chunk_body constructor. 0681 0682 @note This function is provided as a notational convenience 0683 to omit specification of the class template arguments. 0684 */ 0685 template<class ConstBufferSequence, class... Args> 0686 auto 0687 make_chunk( 0688 ConstBufferSequence const& buffers, 0689 Args&&... args) -> 0690 chunk_body<ConstBufferSequence> 0691 { 0692 return chunk_body<ConstBufferSequence>( 0693 buffers, std::forward<Args>(args)...); 0694 } 0695 0696 /** Returns a @ref chunk_last 0697 0698 @note This function is provided as a notational convenience 0699 to omit specification of the class template arguments. 0700 */ 0701 inline 0702 chunk_last<chunk_crlf> 0703 make_chunk_last() 0704 { 0705 return chunk_last<chunk_crlf>{}; 0706 } 0707 0708 /** Returns a @ref chunk_last 0709 0710 This function construct and returns a complete 0711 @ref chunk_last for a last chunk containing the 0712 specified trailers. 0713 0714 @param trailer A ConstBufferSequence or 0715 @note This function is provided as a notational convenience 0716 to omit specification of the class template arguments. 0717 0718 @param args Optional arguments passed to the @ref chunk_last 0719 constructor. 0720 */ 0721 template<class Trailer, class... Args> 0722 chunk_last<Trailer> 0723 make_chunk_last( 0724 Trailer const& trailer, 0725 Args&&... args) 0726 { 0727 return chunk_last<Trailer>{ 0728 trailer, std::forward<Args>(args)...}; 0729 } 0730 0731 } // http 0732 } // beast 0733 } // boost 0734 0735 #include <boost/beast/http/impl/chunk_encode.hpp> 0736 0737 #endif
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |