Hello,

After  using boost::asio for several years I thought, I might give beast a try. 
I need to write a http server processing a POST request with an upload of a big 
file. So I thought, I could start with libs/beast/example/http/server/async. I 
soon found the function handle_request() and that I have to add something like

if (req.method() == http::verb::post && req.target()=="/xxx" )

to catch the http POST transaction. But since I have to process the upload of a 
large file, I thought that using a http::string_body might not be the best 
choice. I found several other body types in the documentation.  I thought
buffer_body ought to be fine, since the documentation says: ‘This allows for 
serialization of body data coming from external sources, and incremental 
parsing of message body content using a fixed size buffer.’.

incremental processing of the input stream is what I need. But now, I have no 
clue, how to change the example to use a buffer_body.

I changed http::request<http::string_body> req_ to 
http::request<http::buffer_body> req_. But now I must process the request 
message in chunks.

How do I get my callback invoked for each chunk?
Without additional changes, I get a read error: need buffer.

But the documentation on buffer_body does not help me. Buffer_body does not 
seem to have any methods, that I can call.
It does have a member type reader, that is documented as 
implementation-defined. So there is nothing I can do with this reader. ☹
There is a member type value_type, that does have data, size and more mebers, 
but I have no idea, how I could et hold of a variable of this type containing a 
part of my message body.

The error message might indicate, that I need to provide a fixed size buffer to 
the buffer_body, but I have no idea, how to do this.

I tried to add the following code to do_read():

             req_.body().data = my_buffer;
             req_.body().size = sizeof(my_buffer);

It compiles, so req_body() seems to be the way to get hold on a 
http::buffer_body::value_type, but simply initializing the two variables does 
not seem to be sufficient. I also tried to set req_.body().more to false or to 
true, but it didn’t change anything.

I then thought, I might try a dynamic_body. This would store the entire upload 
in memory, but perhaps I get more familiar with the beat framework, when I try 
to use this body.

And in deed, I managed to write some code, that shows all request headers and 
the request body on stdout. To get the body, I had to copy the buffer contents 
into a std::string:

             std::string body{ boost::asio::buffers_begin(req.body().data()),
                               boost::asio::buffers_end(req.body().data()) };

Since large files have to be handled by my code, this additional copy of the 
data is to be avoided. So I tried to iterate the body using the iterators:

             const auto begin = boost::asio::buffers_begin(req.body().data());
             const auto end   = boost::asio::buffers_end(req.body().data());
             for (auto it = begin; it != end; it++)
                    putchar(*it);

While it runs fine on the windows box, the loop crashes on linux in the 512th 
iteration in it++.

Program received signal SIGSEGV, Segmentation fault.
0x0000555555592432 in boost::intrusive::list_node_traits<void*>::get_previous 
(n=@0x7fffffffc118: 0x1ff) at ../boost/boost/intrusive/detail/list_node.hpp:54
54         {  return n->prev_;  }
(gdb) print n
$1 = (const boost::intrusive::list_node_traits<void*>::node_ptr &) 
@0x7fffffffc118: 0x1ff
(gdb)

Here is the call stack:
#0  0x0000555555592432 in 
boost::intrusive::list_node_traits<void*>::get_previous (n=@0x7fffffffc118: 
0x1ff) at ../boost/boost/intrusive/detail/list_node.hpp:54
#1  
boost::intrusive::list_iterator<boost::intrusive::bhtraits<boost::beast::basic_multi_buffer<std::allocator<char>
 >::element, boost::intrusive::list_node_traits<void*>, 
(boost::intrusive::link_mode_type)0, boost::intrusive::dft_tag, 1u>, 
true>::operator-- (this=0x7fffffffc118) at 
../boost/boost/intrusive/detail/list_iterator.hpp:107
#2  
std::__advance<boost::intrusive::list_iterator<boost::intrusive::bhtraits<boost::beast::basic_multi_buffer<std::allocator<char>
 >::element, boost::intrusive::list_node_traits<void*>, 
(boost::intrusive::link_mode_type)0, boost::intrusive::dft_tag, 1u>, true>, 
long> (__i=..., __n=0) at 
/usr/lib/gcc/x86_64-pc-linux-gnu/10.2.0/include/g++-v10/bits/stl_iterator_base_funcs.h:169
#3  0x000055555558daf0 in 
std::advance<boost::intrusive::list_iterator<boost::intrusive::bhtraits<boost::beast::basic_multi_buffer<std::allocator<char>
 >::element, boost::intrusive::list_node_traits<void*>, 
(boost::intrusive::link_mode_type)0, boost::intrusive::dft_tag, 1u>, true>, 
long> (__i=..., __n=-1) at 
/usr/lib/gcc/x86_64-pc-linux-gnu/10.2.0/include/g++-v10/bits/stl_iterator_base_funcs.h:206
#4  0x0000555555589254 in 
std::prev<boost::intrusive::list_iterator<boost::intrusive::bhtraits<boost::beast::basic_multi_buffer<std::allocator<char>
 >::element, boost::intrusive::list_node_traits<void*>, 
(boost::intrusive::link_mode_type)0, boost::intrusive::dft_tag, 1u>, true> > 
(__x=..., __n=1) at 
/usr/lib/gcc/x86_64-pc-linux-gnu/10.2.0/include/g++-v10/bits/stl_iterator_base_funcs.h:230
#5  0x0000555555589608 in boost::beast::basic_multi_buffer<std::allocator<char> 
>::subrange<true>::const_iterator::operator* (this=0x7fffffffc4f8) at 
../boost/boost/beast/core/impl/multi_buffer.hpp:384
#6  0x0000555555589b4b in 
boost::asio::buffers_iterator<boost::beast::basic_multi_buffer<std::allocator<char>
 >::subrange<true>, char>::increment (this=0x7fffffffc4d0)
    at ../boost/boost/asio/buffers_iterator.hpp:370
#7  0x0000555555584894 in 
boost::asio::buffers_iterator<boost::beast::basic_multi_buffer<std::allocator<char>
 >::subrange<true>, char>::operator++ (this=0x7fffffffc4d0)
    at ../boost/boost/asio/buffers_iterator.hpp:229
#8  0x000055555557e7c0 in 
boost::asio::buffers_iterator<boost::beast::basic_multi_buffer<std::allocator<char>
 >::subrange<true>, char>::operator++ (this=0x7fffffffc4d0)
    at ../boost/boost/asio/buffers_iterator.hpp:237
#9  0x0000555555579ba8 in 
handle_request<boost::beast::http::basic_dynamic_body<boost::beast::basic_multi_buffer<std::allocator<char>
 > >, std::allocator<char>, session::send_lambda&> (doc_root=...,
    req=..., send=...) at t.cpp:164

I hope anybody can give my a hint on how to use this beast.

Right now it feels that it might be easier to write the http server using plain 
boost::asio.


Klebsch Mario
Funktion | R&D



Tel: +49 (0) 531 38 701 718
Raum: Braunschweig, E20



Diese E-Mail und die an sie angehängten Dateien sind ausschließlich für 
Personen oder Institutionen bestimmt, deren Namen oben aufgeführt sind. Sie 
können Informationen enthalten, die durch das Berufsgeheimnis geschützt sind 
und deren Weitergabe strengstens untersagt ist. Jede elektronische Nachricht 
kann geändert werden. ACTIA lehnt jede Verantwortung für diese Nachricht ab. 
Der Inhalt dieser Nachricht stellt keine Verpflichtung seitens unseres 
Unternehmens dar. Wenn Sie kein Empfänger sind, weisen wir Sie darauf hin, dass 
das Lesen, Vervielfältigen oder Verteilen strengstens untersagt ist. Wir bitten 
Sie daher, uns umgehend über diesen Brief zu informieren und diese Nachricht 
sowie eventuell beigefügte Unterlagen aus Ihrem Postfach zu löschen. Danke.

This e-mail and the files attached to it are intended exclusively for persons 
or institutions whose names are listed above. They may contain information that 
is protected by professional secrecy and the disclosure of which is strictly 
prohibited. Any electronic message can be modified. ACTIA declines all 
responsibility for this message. The content of this message does not represent 
a commitment on the part of our company. If you are not a recipient, we would 
like to point out that reading, copying or distribution is strictly prohibited. 
We therefore ask you to inform us immediately about this letter and to delete 
this message and any accompanying documents from your mailbox. Thank you.



_______________________________________________
Boost-users mailing list
Boost-users@lists.boost.org
https://lists.boost.org/mailman/listinfo.cgi/boost-users

Reply via email to