In my application I want to stream jpg images through a HTTP web server using the POCO library, and for this I am using multipart/x-mixed-replace
content type in my response body. This means when a GET
request arrives to the HTTP server, it is continously sending images to the client in parts in a single http response.
The stream should close and the request handler should return when the client closes the window. But my problem with the HTTPServerResponse.send()
stream is that it only gets destroyed, when the response object is destroyed, so I do not know when the client has left, and when do I have to stop sending the images.
That is how the code looks like:
#pragma once
#include <fstream>
#include <sstream>
#include <string>
#include "Poco/Net/HTTPRequestHandler.h"
class StreamHandler : public Poco::Net::HTTPRequestHandler {
public:
void handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response) override {
std::ifstream imgFile("../../assets/imgs/random.jpg");
std::stringstream ss{};
ss << imgFile.rdbuf();
std::string buf = ss.str();
std::string boundary = "--BOUNDARY--";
response.setVersion(request.getVersion());
response.setStatus(Poco::Net::HTTPServerResponse::HTTP_OK);
response.setChunkedTransferEncoding(false);
response.setKeepAlive(false);
response.setContentType("multipart/x-mixed-replace; boundary=" + boundary);
response.set("Access-Control-Allow-Origin", "*");
response.set("Connection", "Close");
response.set("Cache-Control",
"no-cache, no-store, must-revalidate, pre-check=0, post-check=0, max-age=0, false");
response.set("Pragma", "no-cache");
std::ostream& ostr = response.send();
while (true) { // <-- What is the stop condition?
ostr << boundary << "\r\n";
ostr << "Content-Type: image/jpeg\r\n"
"Content-Length: " +
std::to_string(buf.length()) + "\r\n\r\n";
ostr << buf;
ostr << "\r\n";
}
}
};
Is there a way to detect whether the client has left?
PS: Possibly I would like a solution within the boundaries of Poco::Net::HTTPRequestHandler
. I do not want any solution that requires opening another port, or using another third party library only for the streaming. For example, I am already using nadjieb/cpp-mjpeg-streamer which is working great, but I want to simplify my code and depend only on POCO. In lower level libraries I saw good implementations that are using the following strategy:
while (true) {
if (res) {
res = http_res_send_chunk(req, part_buf, part_len);
} else {
break;
}
}
The send command returns with some positive integer in case of success, and with 0 if the send function failed. However, I cannot replicate this with POCO unfortunately. Any ideas how to get around this?