Boost logo

Boost :

Subject: Re: [boost] [review][beast] Review of Beast starts today : July 1 - July 10
From: Niall Douglas (s_sourceforge_at_[hidden])
Date: 2017-07-03 01:43:11


>> 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_parser<http::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_parser<http::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::response<http::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/

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk