Boost logo

Boost :

Subject: Re: [boost] [beast] Chunking example
From: Vinnie Falco (vinnie.falco_at_[hidden])
Date: 2017-07-02 14:44:37


On Sun, Jul 2, 2017 at 7:34 AM, Bjorn Reese via Boost
<boost_at_[hidden]> wrote:
> So chunk-ext fields are not passed to the user unless they write a
> parser to extract them?

If you want the chunk extensions you have to subclass basic_parser
(not the same as writing a parser). Here's an example of what a
user-defined subclass could start with:

    template<bool isRequest, class Body,
        class Allocator = std::allocator<char>>
    class parser
        : public basic_parser<isRequest,
            parser<isRequest, Body, Allocator>>
    {
        using base_type = basic_parser<isRequest,
            parser<isRequest, Body, Allocator>>;

        message<isRequest, Body, basic_fields<Allocator>> m_;
        boost::optional<typename Body::writer> wr_;

    public:
        using value_type =
            message<isRequest, Body, basic_fields<Allocator>>;

        parser() = default;
        parser(parser const&) = delete;
        parser(parser&& other) = default;
        parser& operator=(parser const&) = delete;

        template<class... Args>
        explicit
        parser(Args&&... args)
          : m_(std::forward<Args>(args))
        {
        }

        value_type const&
        get() const { return m_; }
        value_type& get() { return m_; }
        value_type release() { return std::move(m_); }

    private:
        friend class basic_parser<isRequest, parser>;

        void
        on_request(verb method, string_view method_str,
            string_view target, int version, error_code& ec)
        {
            try
            {
                m_.target(target);
                if(method != verb::unknown)
                    m_.method(method);
                else
                    m_.method_string(method_str);
                ec.assign(0, ec.category());
            }
            catch(std::bad_alloc const&)
            {
                ec = error::bad_alloc;
            }
            m_.version = version;
        }

        void
        on_response(int code,
            string_view reason,
                int version, error_code& ec)
        {
            m_.result(code);
            m_.version = version;
            try
            {
                m_.reason(reason);
                ec.assign(0, ec.category());
            }
            catch(std::bad_alloc const&)
            {
                ec = error::bad_alloc;
            }
        }

        void
        on_field(field name, string_view name_string,
            string_view value, error_code& ec)
        {
            try
            {
                m_.insert(name, name_string, value);
                ec.assign(0, ec.category());
            }
            catch(std::bad_alloc const&)
            {
                ec = error::bad_alloc;
            }
        }

        void
        on_header(error_code& ec)
        {
            ec.assign(0, ec.category());
        }

        void
        on_body(boost::optional<
            std::uint64_t> const& content_length,
                error_code& ec)
        {
            wr_.emplace(m_, content_length, ec);
        }

        std::size_t
        on_data(string_view s, error_code& ec)
        {
            return wr_->put(boost::asio::buffer(
                s.data(), s.size()), ec);
        }

        void
        on_chunk(std::uint64_t size,
            string_view ext, error_code& ec)
        {
            ec.assign(0, ec.category());
        }

        void
        on_complete(error_code& ec)
        {
            if(wr_)
                wr_->finish(ec);
            else
                ec.assign(0, ec.category());
        }
    };

The function on_chunk() is called for each new chunk header, and gets
passed the size of the chunk as well as the extension.


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk