nnrales
nnrales

Reputation: 1519

Convert boost serialized object's asio::streambuf representation into Beast's DynamicBody req.body()

    // Serialize using boost serialization        
    boost::asio::streambuf binary_buffer;
    boost::archive::binary_oarchive archive(binary_buffer);
    archive << world_map; 

    //beast::buffers_adaptor<boost::asio::streambuf>(binary_buffer);
    req.body().data() = beast::buffers_adaptor<boost::asio::streambuf>(binary_buffer);

I have this code, where I am try to convert a streambuf into req.body() so that I can send it to the server. Looking through the examples, I am not able to figure out what the right conversion is. buffers_adaptor seems to take in a MutableBuffer and not the ConstBuffer that is produced by asio::streambuf.

How can I fix this?

Upvotes: 1

Views: 602

Answers (1)

sehe
sehe

Reputation: 393134

With dynamic_body the body() is actually a multi_buffer.

So you would need to copy into that:

req.body().prepare(binary_buffer.size());
req.body().commit(binary_buffer.size());
auto n = asio::buffer_copy(req.body().data(), binary_buffer.data());

Example:

req.body().prepare(binary_buffer.size());
req.body().commit(binary_buffer.size());
auto n = asio::buffer_copy(req.body().data(), binary_buffer.data());
req.target("http://example.com");
req.method(http::verb::post);
req.set(http::field::host, "example.com");
req.content_length(n);

std::cout << req << std::endl;

Prints

POST http://example.com HTTP/1.1
Host: example.coml
Content-Length: 41

22 serialization::archive 18 9 world_map

Simplify

It would be cheaper to just serialize directly into the body buffer. You can using Boost Iostreams and e.g. vector_body:

Live On Coliru

#include <boost/asio/streambuf.hpp>
#include <boost/beast.hpp>
#include <boost/beast/http.hpp>
namespace asio = boost::asio;
namespace beast = boost::beast;
namespace http = beast::http;

#include <boost/iostreams/device/back_inserter.hpp>
#include <boost/iostreams/stream_buffer.hpp>
#include <boost/serialization/serialization.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <iostream>

int main()  {
    http::request<http::vector_body<char> > req;
    {
        namespace io = boost::iostreams;

        using D = io::back_insert_device<std::vector<char> >;
        io::stream_buffer<D> sb(req.body());

        {
            std::ostream os(&sb);
            std::string world_map = "world_map"; // for demo

            boost::archive::text_oarchive archive(os);
            archive << world_map;
        }
    }

    req.target("http://example.com");
    req.method(http::verb::post);
    req.set(http::field::host, "example.com");
    req.content_length(req.body().size());

    std::cout << req << std::endl;
}

Prints

POST http://example.com HTTP/1.1
Host: example.com
Content-Length: 41

22 serialization::archive 18 9 world_map

Upvotes: 1

Related Questions