beast::http::body model for boost::asio::buffer

Created on 24 Jun 2017  Â·  15Comments  Â·  Source: boostorg/beast

What is the correct body model to implement this?

request.body = boost::asio::buffer("Hello, world!");

Most helpful comment

I could add these to buffer_body::value_type

        /// Assign a `boost::asio::const_buffers` to `*this`
        value_type&
        operator=(boost::asio::const_buffer const& b)
        {
            data = boost::asio::buffer_cast<void*>(b);
            size = boost::asio::buffer_size(b);
            return *this;
        }

        /// Assign a `boost::asio::const_buffers_1` to `*this`
        value_type&
        operator=(boost::asio::const_buffers_1 const& b)
        {
            data = boost::asio::buffer_cast<void*>(b);
            size = boost::asio::buffer_size(b);
            return *this;
        }

I'm working on it now

All 15 comments

void blub1()
{
    beast::http::request<beast::http::string_view_body> request;
    request.body = boost::asio::buffer("Hello, world!");
}
void blub2()
{
    beast::http::request<beast::http::buffer_body> request;
    request.body = boost::asio::buffer("Hello, world!");
}

==>

gcc.compile.c++ bin/gcc-7/release/example/foo.o

    "g++"  -ftemplate-depth-128 -march=native -ftemplate-depth=256 -std=c++17 -O3 -finline-functions -Wno-inline -Wall -fPIC  -DBOOST_ALL_DYN_LINK -DNDEBUG  -I"/home/mike/workspace/Beast/include" -I"include" -c -o "bin/gcc-7/release/example/foo.o" "example/foo.cpp"

example/foo.cpp: In function ‘void blub1()’:
example/foo.cpp:168:55: error: no match for ‘operator=’ (operand types are ‘beast::http::string_view_body::value_type {aka boost::basic_string_ref<char, std::char_traits<char> >}’ and ‘boost::asio::const_buffers_1’)
     request.body = boost::asio::buffer("Hello, world!");
                                                       ^
In file included from /home/mike/workspace/Beast/include/beast/core/string.hpp:11:0,
                 from /home/mike/workspace/Beast/include/beast/core/static_string.hpp:12,
                 from /home/mike/workspace/Beast/include/beast/core.hpp:29,
                 from /home/mike/workspace/Beast/include/beast.hpp:13,
                 from example/foo.cpp:8:
/usr/include/boost/utility/string_ref.hpp:77:27: note: candidate: constexpr boost::basic_string_ref<charT, traits>& boost::basic_string_ref<charT, traits>::operator=(const boost::basic_string_ref<charT, traits>&) [with charT = char; traits = std::char_traits<char>]
         basic_string_ref& operator=(const basic_string_ref &rhs) BOOST_NOEXCEPT
                           ^~~~~~~~
/usr/include/boost/utility/string_ref.hpp:77:27: note:   no known conversion for argument 1 from ‘boost::asio::const_buffers_1’ to ‘const boost::basic_string_ref<char, std::char_traits<char> >&’
example/foo.cpp: In function ‘void blub2()’:
example/foo.cpp:173:55: error: no match for ‘operator=’ (operand types are ‘beast::http::buffer_body::value_type’ and ‘boost::asio::const_buffers_1’)
     request.body = boost::asio::buffer("Hello, world!");
                                                       ^
In file included from /home/mike/workspace/Beast/include/beast/http.hpp:14:0,
                 from /home/mike/workspace/Beast/include/beast.hpp:14,
                 from example/foo.cpp:8:
/home/mike/workspace/Beast/include/beast/http/buffer_body.hpp:30:12: note: candidate: constexpr beast::http::buffer_body::value_type& beast::http::buffer_body::value_type::operator=(const beast::http::buffer_body::value_type&)
     struct value_type
            ^~~~~~~~~~
/home/mike/workspace/Beast/include/beast/http/buffer_body.hpp:30:12: note:   no known conversion for argument 1 from ‘boost::asio::const_buffers_1’ to ‘const beast::http::buffer_body::value_type&’
/home/mike/workspace/Beast/include/beast/http/buffer_body.hpp:30:12: note: candidate: constexpr beast::http::buffer_body::value_type& beast::http::buffer_body::value_type::operator=(beast::http::buffer_body::value_type&&)
/home/mike/workspace/Beast/include/beast/http/buffer_body.hpp:30:12: note:   no known conversion for argument 1 from ‘boost::asio::const_buffers_1’ to ‘beast::http::buffer_body::value_type&&’
...failed gcc.compile.c++ bin/gcc-7/release/example/foo.o...

Oh, you literally want to assign a boost::asio::const_buffers_1. There's no way to do that. I thought you were asking the more general question "which body type represents a non-owning buffer". I don't see much point to a body whose value_type is boost::asio::const_buffers_1, you can get the same behavior using buffer_body and just set fields of the value_type to point to your buffer:

void foo(boost::asio::const_buffers_1 cb)
{
  response<buffer_body> res;
  res.body.data = boost::asio::buffer_cast<void const*>(cb);
  res.body.size = boost::asio::buffer_size(cb);
  res.body.more = false;
}

Is this still an issue?

Not really -> close :-)

I could add these to buffer_body::value_type

        /// Assign a `boost::asio::const_buffers` to `*this`
        value_type&
        operator=(boost::asio::const_buffer const& b)
        {
            data = boost::asio::buffer_cast<void*>(b);
            size = boost::asio::buffer_size(b);
            return *this;
        }

        /// Assign a `boost::asio::const_buffers_1` to `*this`
        value_type&
        operator=(boost::asio::const_buffers_1 const& b)
        {
            data = boost::asio::buffer_cast<void*>(b);
            size = boost::asio::buffer_size(b);
            return *this;
        }

I'm working on it now

So this would compile?

void blub2()
{
    beast::http::request<beast::http::buffer_body> request;
    request.body = boost::asio::buffer("Hello, world!");
}

Yes, it should. I'm adding a test for it.

Hmm... uh oh, seems like there's a problem. buffer_body has to be mutable. I might have to break this up into two classes... ugh

Unfortunately no, this doesn't work. Because value_type::data is void* not void const*. I would have to cast away the const-ness. I am thinking about making two classes
buffer_body which would be const, and mutable_buffer_body which would be mutable.

Sounds like the pattern i suggested for strings too:

Strings:

  • mutable_sting_body for write and read
  • immutable_sting_body for write only

Buffers:

  • mutable_buffer_body for write and read
  • immutable_buffer_body for write only

const not immutable

But the basic idea is the same - only different names :-)

I don't like how this turned out, it makes a small issue with the HTTP relay example worse. I am going to have to leave it alone for now, and revisit it later. I will open an issue.

Closing this

Was this page helpful?
0 / 5 - 0 ratings

Related issues

inetic picture inetic  Â·  4Comments

chrgrd picture chrgrd  Â·  4Comments

fpingas picture fpingas  Â·  7Comments

nguoithichkhampha picture nguoithichkhampha  Â·  7Comments

jed1 picture jed1  Â·  4Comments