Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-14 08:26:51

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_SERIALIZER_HPP
0011 #define BOOST_BEAST_HTTP_SERIALIZER_HPP
0012 
0013 #include <boost/beast/core/detail/config.hpp>
0014 #include <boost/beast/core/buffers_cat.hpp>
0015 #include <boost/beast/core/buffers_prefix.hpp>
0016 #include <boost/beast/core/buffers_suffix.hpp>
0017 #include <boost/beast/core/string.hpp>
0018 #include <boost/beast/core/detail/variant.hpp>
0019 #include <boost/beast/http/message.hpp>
0020 #include <boost/beast/http/chunk_encode.hpp>
0021 #include <boost/asio/buffer.hpp>
0022 #include <boost/optional.hpp>
0023 
0024 namespace boost {
0025 namespace beast {
0026 namespace http {
0027 
0028 /** Provides buffer oriented HTTP message serialization functionality.
0029 
0030     An object of this type is used to serialize a complete
0031     HTTP message into a sequence of octets. To use this class,
0032     construct an instance with the message to be serialized.
0033     The implementation will automatically perform chunk encoding
0034     if the contents of the message indicate that chunk encoding
0035     is required.
0036 
0037     Chunked output produced by the serializer never contains chunk
0038     extensions or trailers, and the location of chunk boundaries
0039     is not specified. If callers require chunk extensions, trailers,
0040     or control over the exact contents of each chunk they should
0041     use the serializer to write just the message header, and then
0042     assume control over serializing the chunked payload by using
0043     the chunk buffer sequence types @ref chunk_body, @ref chunk_crlf,
0044     @ref chunk_header, and @ref chunk_last.
0045 
0046     @note
0047 
0048     Moving or copying the serializer after the first call to
0049     @ref serializer::next results in undefined behavior. Try to heap-allocate
0050     the serializer object if you need to move the serializer between multiple
0051     async operations (for example, between a call to `async_write_header` and
0052     `async_write`).
0053 
0054     @tparam isRequest `true` if the message is a request.
0055 
0056     @tparam Body The body type of the message.
0057 
0058     @tparam Fields The type of fields in the message.
0059 */
0060 template<
0061     bool isRequest,
0062     class Body,
0063     class Fields = fields>
0064 class serializer
0065 {
0066 public:
0067     static_assert(is_body<Body>::value,
0068         "Body type requirements not met");
0069 
0070     static_assert(is_body_writer<Body>::value,
0071         "BodyWriter type requirements not met");
0072 
0073     /** The type of message this serializer uses
0074 
0075         This may be const or non-const depending on the
0076         implementation of the corresponding <em>BodyWriter</em>.
0077     */
0078 #if BOOST_BEAST_DOXYGEN
0079     using value_type = __implementation_defined__;
0080 #else
0081     using value_type = typename std::conditional<
0082         std::is_constructible<typename Body::writer,
0083             header<isRequest, Fields>&,
0084             typename Body::value_type&>::value &&
0085         ! std::is_constructible<typename Body::writer,
0086             header<isRequest, Fields> const&,
0087             typename Body::value_type const&>::value,
0088         message<isRequest, Body, Fields>,
0089         message<isRequest, Body, Fields> const>::type;
0090 #endif
0091 
0092 private:
0093     enum
0094     {
0095         do_construct        =   0,
0096 
0097         do_init             =  10,
0098         do_header_only      =  20,
0099         do_header           =  30,
0100         do_body             =  40,
0101         
0102         do_init_c           =  50,
0103         do_header_only_c    =  60,
0104         do_header_c         =  70,
0105         do_body_c           =  80,
0106         do_final_c          =  90,
0107     #ifndef BOOST_BEAST_NO_BIG_VARIANTS
0108         do_body_final_c     = 100,
0109         do_all_c            = 110,
0110     #endif
0111 
0112         do_complete         = 120
0113     };
0114 
0115     void fwrinit(std::true_type);
0116     void fwrinit(std::false_type);
0117 
0118     template<std::size_t, class Visit>
0119     void
0120     do_visit(error_code& ec, Visit& visit);
0121 
0122     using writer = typename Body::writer;
0123 
0124     using cb1_t = buffers_suffix<typename
0125         Fields::writer::const_buffers_type>;        // header
0126     using pcb1_t  = buffers_prefix_view<cb1_t const&>;
0127 
0128     using cb2_t = buffers_suffix<buffers_cat_view<
0129         typename Fields::writer::const_buffers_type,// header
0130         typename writer::const_buffers_type>>;      // body
0131     using pcb2_t = buffers_prefix_view<cb2_t const&>;
0132 
0133     using cb3_t = buffers_suffix<
0134         typename writer::const_buffers_type>;       // body
0135     using pcb3_t = buffers_prefix_view<cb3_t const&>;
0136 
0137     using cb4_t = buffers_suffix<buffers_cat_view<
0138         typename Fields::writer::const_buffers_type,// header
0139         detail::chunk_size,                         // chunk-size
0140         net::const_buffer,                          // chunk-ext
0141         chunk_crlf,                                 // crlf
0142         typename writer::const_buffers_type,        // body
0143         chunk_crlf>>;                               // crlf
0144     using pcb4_t = buffers_prefix_view<cb4_t const&>;
0145 
0146     using cb5_t = buffers_suffix<buffers_cat_view<
0147         detail::chunk_size,                         // chunk-header
0148         net::const_buffer,                          // chunk-ext
0149         chunk_crlf,                                 // crlf
0150         typename writer::const_buffers_type,        // body
0151         chunk_crlf>>;                               // crlf
0152     using pcb5_t = buffers_prefix_view<cb5_t const&>;
0153 
0154     using cb6_t = buffers_suffix<buffers_cat_view<
0155         detail::chunk_size,                         // chunk-header
0156         net::const_buffer,                          // chunk-size
0157         chunk_crlf,                                 // crlf
0158         typename writer::const_buffers_type,        // body
0159         chunk_crlf,                                 // crlf
0160         net::const_buffer,                          // chunk-final
0161         net::const_buffer,                          // trailers 
0162         chunk_crlf>>;                               // crlf
0163     using pcb6_t = buffers_prefix_view<cb6_t const&>;
0164 
0165     using cb7_t = buffers_suffix<buffers_cat_view<
0166         typename Fields::writer::const_buffers_type,// header
0167         detail::chunk_size,                         // chunk-size
0168         net::const_buffer,                          // chunk-ext
0169         chunk_crlf,                                 // crlf
0170         typename writer::const_buffers_type,        // body
0171         chunk_crlf,                                 // crlf
0172         net::const_buffer,                          // chunk-final
0173         net::const_buffer,                          // trailers 
0174         chunk_crlf>>;                               // crlf
0175     using pcb7_t = buffers_prefix_view<cb7_t const&>;
0176 
0177     using cb8_t = buffers_suffix<buffers_cat_view<
0178         net::const_buffer,                          // chunk-final
0179         net::const_buffer,                          // trailers 
0180         chunk_crlf>>;                               // crlf
0181     using pcb8_t = buffers_prefix_view<cb8_t const&>;
0182 
0183     value_type& m_;
0184     writer wr_;
0185     boost::optional<typename Fields::writer> fwr_;
0186     beast::detail::variant<
0187         cb1_t, cb2_t, cb3_t, cb4_t,
0188         cb5_t ,cb6_t, cb7_t, cb8_t> v_;
0189     beast::detail::variant<
0190         pcb1_t, pcb2_t, pcb3_t, pcb4_t,
0191         pcb5_t ,pcb6_t, pcb7_t, pcb8_t> pv_;
0192     std::size_t limit_ =
0193         (std::numeric_limits<std::size_t>::max)();
0194     int s_ = do_construct;
0195     bool split_ = false;
0196     bool header_done_ = false;
0197     bool more_ = false;
0198 
0199 public:
0200     /** Move Constructor
0201         @note
0202 
0203         Moving or copying the serializer after the first call to
0204         @ref serializer::next results in undefined behavior. Try to heap-allocate
0205         the serializer object if you need to move the serializer between multiple
0206         async operations (for example, between a call to `async_write_header` and
0207         `async_write`).
0208     */
0209     serializer(serializer&&) = default;
0210 
0211     /** Copy Constructor
0212         @note
0213 
0214         Moving or copying the serializer after the first call to
0215         @ref serializer::next results in undefined behavior. Try to heap-allocate
0216         the serializer object if you need to move the serializer between multiple
0217         async operations (for example, between a call to `async_write_header` and
0218         `async_write`).
0219     */
0220     serializer(serializer const&) = default;
0221 
0222     /// Assignment
0223     serializer& operator=(serializer const&) = delete;
0224 
0225     /** Constructor
0226 
0227         The implementation guarantees that the message passed on
0228         construction will not be accessed until the first call to
0229         @ref next. This allows the message to be lazily created.
0230         For example, if the header is filled in before serialization.
0231 
0232         @param msg A reference to the message to serialize, which must
0233         remain valid for the lifetime of the serializer. Depending on
0234         the type of Body used, this may or may not be a `const` reference.
0235 
0236         @note This function participates in overload resolution only if
0237         Body::writer is constructible from a `const` message reference.
0238     */
0239     explicit
0240     serializer(value_type& msg);
0241 
0242     /// Returns the message being serialized
0243     value_type&
0244     get()
0245     {
0246         return m_;
0247     }
0248 
0249     /// Returns the serialized buffer size limit
0250     std::size_t
0251     limit()
0252     {
0253         return limit_;
0254     }
0255 
0256     /** Set the serialized buffer size limit
0257 
0258         This function adjusts the limit on the maximum size of the
0259         buffers passed to the visitor. The new size limit takes effect
0260         in the following call to @ref next.
0261 
0262         The default is no buffer size limit.
0263 
0264         @param limit The new buffer size limit. If this number
0265         is zero, the size limit is removed.
0266     */
0267     void
0268     limit(std::size_t limit)
0269     {
0270         limit_ = limit > 0 ? limit :
0271             (std::numeric_limits<std::size_t>::max)();
0272     }
0273 
0274     /** Returns `true` if we will pause after writing the complete header.
0275     */
0276     bool
0277     split()
0278     {
0279         return split_;
0280     }
0281 
0282     /** Set whether the header and body are written separately.
0283 
0284         When the split feature is enabled, the implementation will
0285         write only the octets corresponding to the serialized header
0286         first. If the header has already been written, this function
0287         will have no effect on output.
0288     */
0289     void
0290     split(bool v)
0291     {
0292         split_ = v;
0293     }
0294 
0295     /** Return `true` if serialization of the header is complete.
0296 
0297         This function indicates whether or not all buffers containing
0298         serialized header octets have been retrieved.
0299     */
0300     bool
0301     is_header_done()
0302     {
0303         return header_done_;
0304     }
0305 
0306     /** Return `true` if serialization is complete.
0307 
0308         The operation is complete when all octets corresponding
0309         to the serialized representation of the message have been
0310         successfully retrieved.
0311     */
0312     bool
0313     is_done() const
0314     {
0315         return s_ == do_complete;
0316     }
0317 
0318     /** Returns the next set of buffers in the serialization.
0319 
0320         This function will attempt to call the `visit` function
0321         object with a <em>ConstBufferSequence</em> of unspecified type
0322         representing the next set of buffers in the serialization
0323         of the message represented by this object. 
0324 
0325         If there are no more buffers in the serialization, the
0326         visit function will not be called. In this case, no error
0327         will be indicated, and the function @ref is_done will
0328         return `true`.
0329 
0330         @param ec Set to the error, if any occurred.
0331 
0332         @param visit The function to call. The equivalent function
0333         signature of this object must be:
0334         @code
0335             template<class ConstBufferSequence>
0336             void visit(error_code&, ConstBufferSequence const&);
0337         @endcode
0338         The function is not copied, if no error occurs it will be
0339         invoked before the call to @ref next returns.
0340 
0341     */
0342     template<class Visit>
0343     void
0344     next(error_code& ec, Visit&& visit);
0345 
0346     /** Consume buffer octets in the serialization.
0347 
0348         This function should be called after one or more octets
0349         contained in the buffers provided in the prior call
0350         to @ref next have been used.
0351 
0352         After a call to @ref consume, callers should check the
0353         return value of @ref is_done to determine if the entire
0354         message has been serialized.
0355 
0356         @param n The number of octets to consume. This number must
0357         be greater than zero and no greater than the number of
0358         octets in the buffers provided in the prior call to @ref next.
0359     */
0360     void
0361     consume(std::size_t n);
0362 
0363     /** Provides low-level access to the associated <em>BodyWriter</em>
0364 
0365         This function provides access to the instance of the writer
0366         associated with the body and created by the serializer
0367         upon construction. The behavior of accessing this object
0368         is defined by the specification of the particular writer
0369         and its associated body.
0370 
0371         @return A reference to the writer.
0372     */
0373     writer&
0374     writer_impl()
0375     {
0376         return wr_;
0377     }
0378 };
0379 
0380 /// A serializer for HTTP/1 requests
0381 template<class Body, class Fields = fields>
0382 using request_serializer = serializer<true, Body, Fields>;
0383 
0384 /// A serializer for HTTP/1 responses
0385 template<class Body, class Fields = fields>
0386 using response_serializer = serializer<false, Body, Fields>;
0387 
0388 } // http
0389 } // beast
0390 } // boost
0391 
0392 #include <boost/beast/http/impl/serializer.hpp>
0393 
0394 #endif