What I didn't do was write essays of detail. It would take too long, it's not my place, and I'm pretty sure Vinnie knows ASIO internals as well as I do, so I am assuming he understands everything I'm writing.
I understand everything you're writing, but the complete picture still eludes me. Specific examples:
http::request_parserhttp::string_body parser;
parser.header_limit( 8192 ); parser.body_limit( 8192 );
http::read( socket_, buffer, parser, ec );
/*...*/
do_request( parser.get(), ec );
How would this look like in the blobs in, blobs out model?
Slightly more bare metal because you talk to ASIO by hand, but nothing too awful I think: ``` char buffer[16384]; // no need to explicitly limit header + body // Create a HTTP request parsing view of char[16384] http::request_parserhttp::string_body parser(buffer); // Read enough data to parse the request char *p = buffer; do { p += asio::read(socket, asio::buffer(p, buffer + sizeof(buffer) - p)); } while(!parser.has_body(p - buffer)); do_request(parser.get(), ec); // Use any spill at the end memcpy(buffer, buffer + parser.size_bytes(), p - (buffer + parser.size_bytes())); p = buffer; ... ```
Same question for the reverse one:
std::vector<unsigned char> data;
/* ... fill data... */
beast::string_view sv( (char*)data.data(), data.size() ); http::responsehttp::string_view_body res( sv );
res.result( http::status::ok );
res.set( http::field::server, BEAST_VERSION_STRING ); res.set( http::field::content_type, "image/bmp" ); res.set( http::field::content_length, data.size() );
http::write( socket_, res, ec );
How does the ASIO-decoupled code look?
``` std::vector<unsigned char> data; // Create a response borrowing 'data' as a single contiguous // gather buffer, known from it matching ContiguousContainer concept http::response res(data); // These prepend additional gather buffers for the headers res.result( http::status::ok ); res.set( http::field::server, BEAST_VERSION_STRING ); res.set( http::field::content_type, "image/bmp" ); res.set( http::field::content_length, data.size() ); // Tell ASIO to send the response by gathering all the buffers asio::write(socket, boost::make_iterator_range(res.begin(), res.end())); ``` The latter used a bit of C++ 17 template inferencing and has some unwritten type trait specialisation and free function overloads to tell ASIO about a custom `beast::buffer` type pointed to by the iterators, but otherwise it should be fairly obvious. Do ask any questions if it isn't actually obvious :). It's nearly 3am here so my obviousness radar is probably not working well. Niall -- ned Productions Limited Consulting http://www.nedproductions.biz/ http://ie.linkedin.com/in/nialldouglas/