2017-10-01 19:06 GMT-03:00 Vinnie Falco via Boost
However, I came up with a very simple technique to make this work with Beast by writing just a tiny bit of extra code. The solution is to implement a stream wrapper which meets the requirements of SyncReadStream[1] and/or AsyncReadStream[2] and forwards the calls to read to the "next layer" object, which will be the actual socket or ssl::stream.
The implementation of the icy_stream wrapper can check to see if the first 3 bytes received from the next layer match "ICY" and if so, return a buffer to the caller which replaces those characters with "HTTP/1.1" (or "HTTP/1.0"). With this wrapper, calls to beast::http::read or beast::http::async_read can parse the custom response as a regular HTTP message. The wrapper can embed state information to inform the caller if the "ICY" string was not received.
The declaration for such a wrapper might look like this:
template<class NextLayer> class icy_stream;
Usage for the wrapper:
asio::ip::tcp::socket sock{ios}; icy_streamasio::ip::tcp::socket& stream{sock}; beast::http::responsebeast::http::empty_body res; beast::multi_buffer buffer; beast::http::read(stream, buffer, res);
This technique may of course be generalized to support any desired similar but non-standard HTTP requests or responses in a fashion that is completely transparent to Beast.
You could also try to standardize HTTP/1.1 and HTTP/2.0 under the same interface. The version attribute in the message model[1] might not make sense to all HTTP backends. This discussion reminds me of the difference between inductive reasoning and deductive reasoning. Only the immediate problem is pursued and no attention is given trying to solve the general problem at hand. Also, if beast::http::read is what I'll call, then this implies I need to throw my abstractions in `beast::http` namespace (not a problem, just an observation). However, a problem is the fact that this translation in the stream needs to happen to actually use the Beast message framework. Why a “virtual HTTP stream” needs to exist beyond the virtual field? Why does it need to go to memory? Why isn't just limited to the API? Boost.Http managed to expose this amount of feature without exposing a parser at all. [1] http://vinniefalco.github.io/beast/beast/ref/beast__http__message/version.ht... -- Vinícius dos Santos Oliveira https://vinipsmaker.github.io/