Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-16 08:29:32

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