What is the correct body model to implement this?
request.body = boost::asio::buffer("Hello, world!");
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 readimmutable_sting_body for write onlyBuffers:
mutable_buffer_body for write and readimmutable_buffer_body for write onlyconst 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
Most helpful comment
I could add these to
buffer_body::value_typeI'm working on it now