[Cppcms-users] async_flush_output and multipart/x_mixed_replace
Brought to you by:
artyom-beilis
|
From: Tobias R. <rei...@go...> - 2012-02-06 15:55:28
|
Hello,
I'm trying to get a multipart response by doing a single request. The motivation
behind is a big computation which gives some progress feedback. So far I
stumbled over "context::async_flush_output" which (given that name) should flush
the responding data. Simulating the computational part by using a timer, I
expect to get five distinct responses, each in a second (see following code).
Instead, I get the whole response after the five seconds en bloc. Did I miss
something?
class Application : public cppcms::application
{
int counter_;
booster::aio::deadline_timer timer_;
booster::shared_ptr<cppcms::http::context> context_;
boost::thread thread_;
public:
Application(cppcms::service &srv)
: cppcms::application(srv)
{
timer_.set_io_service(service().get_io_service());
dispatcher().assign("^/compute$", &Application::compute, this);
}
void async_handler(cppcms::http::context::complition_type t)
{
timer_.expires_from_now(booster::ptime::seconds(1));
timer_.async_wait(boost::bind(&Application::compute_thread,
booster::intrusive_ptr<Application>(this)));
}
void flush_output()
{
context_->async_flush_output(boost::bind(&Application::async_handler,
booster::intrusive_ptr<Application>(this), _1));
}
void compute_thread()
{
std::ostream& o = context_->response().out();
if (counter_++ < 5)
{
o << "Content-type: text/plain\n\n";
o << "count: " << counter_ << std::endl;
o << "--progress-token\n";
// flush_output();
service().post(boost::bind(&Application::flush_output,
booster::intrusive_ptr<Application>(this)));
return;
}
o << "Content-type: text/plain\n\n";
o << "Computation finished\n";
o << "--progress-token\n";
context_->async_complete_response();
}
void compute()
{
context_ = release_context();
context_->response().set_content_header("multipart/x-mixed-replace;
boundary=progress-token");
context_->response().out() << "--progress-token\n";
counter_ = 0;
// compute_thread();
thread_ = boost::thread(boost::bind(&Application::compute_thread,
booster::intrusive_ptr<Application>(this)));
}
};
int main(int argc, char** argv)
{
try {
cppcms::service srv(argc, argv);
booster::intrusive_ptr<Application> app = new Application(srv);
srv.applications_pool().mount(app, cppcms::mount_point("/counter"));
srv.run();
}
catch(std::exception const& e) {
std::cerr << e.what() << std::endl;
}
}
On the client side I have a simple Javascript:
var xmlHttp = new XMLHttpRequest();
xmlHttp.multipart = true;
xmlHttp.open('GET', 'counter/compute', true);
xmlHttp.onreadystatechange = function (event)
{
console.log("readystate = " + event.target.readyState + ": " +
event.target.responseText + "\n");
}
xmlHttp.send(null);
Best regards,
Tobias
|