Reputation: 101
I have a local file which some process continuously appends to. I would like to serve that file with boost::beast
.
So far I'm using boost::beast::http::response<boost::beast::http::file_body>
and boost::beast::http::async_write
to send the file to the client. That works very well and it is nice that boost::beast
takes care of everything. However, when the end of the file is reached, it stops the asynchronous writing. I assume that is because is_done
of the underlying serializer
returns true
at this point.
Is it possible to keep the asynchronous writing ongoing so new contents are written to the client as the local file grows (similar to how tail -f
would keep writing the file's contents to stdout)?
I've figured that I might need to use boost::beast::http::response_serializer<boost::beast::http::file_body>
for that kind of customization but I'm not sure how to use it correctly. And do I need to use chunked encoding for that purpose?
Note that keeping the HTTP connection open is not the problem, only writing further output as soon as the file grows.
Upvotes: 1
Views: 1308
Reputation: 101
After some research this problem seems not easily solvable, at least not under GNU/Linux which I'm currently focusing on.
It is possible to use chunked encoding as described in boost::beast
's documentation. I've implemented serving chunks asynchronously from file contents which are also read asynchronously with the help of boost::asio::posix::stream_descriptor
. That works quite well. However, it also stops with an end-of-file error as soon as the end of the file is reached. When using async_wait
via the descriptor I'm getting the error "Operation not supported".
So it simply seems not possible to asynchronously wait for more bytes to be written to a file. That's strange considering tail -f
does exactly that. So I've strace
ed tail -f
and it turns out that it calls inotify_add_watch(4, "path_to_file", IN_MODIFY)
. Hence I assume one actually needs to use inotify
to implement this.
For me it seems easier and more efficient to take control over the process which writes to the file so far to let it prints to stdout. Then I can stream the pipe (similarly to how I've attempted streaming the file) and write the file myself.
However, if one wanted to go down the road, I suppose using inotify
and boost::asio::posix::stream_descriptor
is the answer to the question, at least under GNU/Linux.
Upvotes: 1