Search code examples
c++boost-asiojson-rpcetcdboost-beast

What are the requirements to read and write from an http stream (in boost::beast)?


I would like to use boost::beast to read and write to etcd. For starts, I'd like to be able to do these examples with boost beast. They're easily doable with curl. Etcd can be seen as a key/value store. The functions to set/get (put/range in the examples page) are easy to do with the boost::beast client example. No problems there.

But "watch", I don't understand. According to docs, watch is a continuous stream, unlike the others which are sessions that die instantly after retrieving the result. The curl examples show changing the value and a response on-spot while the watch is still active. I should use that same stream to do everything related to that watch, including stopping it.

My question broadly is: How can I implement this in boost::beast?

Let's say that from the client example I submit ioc.run through a thread with

std::thread t(&std::iocontext::run, &ioc);
t.detach();

Now I have full control of the client in the main thread. Am I supposed to create new http requests and submit them in async_write over the socket object? But then if I do that, I lose the features of boost::beast in wrapping the http header with nice http::request<http::string_body>. Am I supposed to create the headers manually? Or am I supposed to just send json with some kind of line terminator to indicate that a message is over? What does the communication protocol look like?

An example with boost::beast would be great.


Solution

  • It looks like etcd uses "long running requests." For this, you want to use http::read_header[1] or http::async_read_header[2] to obtain the response header, and then use http::read_some[3] or http::async_read_some[4] in a loop to read portions of the response body. For this to work cleanly you want to use the http::buffer_body[5] which is designed for this sort of thing. The HTTP Relay example[6] in the documentation demonstrates the use of buffer_body, and can be adapted to process long-running requests.

    [1] https://www.boost.org/doc/libs/1_69_0/libs/beast/doc/html/beast/ref/boost__beast__http__read_header/overload2.html

    [2] https://www.boost.org/doc/libs/1_69_0/libs/beast/doc/html/beast/ref/boost__beast__http__async_read_header.html

    [3] https://www.boost.org/doc/libs/1_69_0/libs/beast/doc/html/beast/ref/boost__beast__http__read_some/overload2.html

    {4] https://www.boost.org/doc/libs/1_69_0/libs/beast/doc/html/beast/ref/boost__beast__http__async_read_some.html

    [5] https://www.boost.org/doc/libs/1_69_0/libs/beast/doc/html/beast/ref/boost__beast__http__buffer_body.html

    [6] https://www.boost.org/doc/libs/1_69_0/libs/beast/doc/html/beast/more_examples/http_relay.html