[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 |