diff --git a/README.md b/README.md index 36539d8..e159ea9 100644 --- a/README.md +++ b/README.md @@ -14,17 +14,15 @@ See also https://github.com/eidheim/Simple-WebSocket-Server for an easy way to m * Client supports chunked transfer encoding * Timeouts, if any of Server::timeout_request and Server::timeout_content are >0 (default: Server::timeout_request=5 seconds, and Server::timeout_content=300 seconds) * Simple way to add REST resources using regex for path, and anonymous functions -* Possibility to flush response to clients both synchronously (Server::flush) and asynchronously (Server::async_flush). +* Possibility to flush response to clients synchronously (Server::flush). ###Usage -Note: newest version is NOT backward compatible with earlier versions. - See http_examples.cpp or https_examples.cpp for example usage. See particularly the JSON-POST (using Boost.PropertyTree) and the GET /match/[number] examples, which are most relevant. -The default_resource includes example use of Server::flush. Note that Server::async_flush might be slightly slower than Server::flush unless you need to process computationally expensive tasks while simultaneously sending large datasets to a client. +The default_resource includes example use of Server::flush. ### Dependencies @@ -38,7 +36,7 @@ Compile with a C++11 compiler supporting regex (for instance g++ 4.9): On Linux using g++: add `-pthread` -Note: added `-lboost_filesystem` for the default_resource example, and `-lboost_thread` to make the json-example thread safe. Also added `-lboost_coroutine -lboost_context` to make synchronous and asynchronous flushing of response stream work. On some systems you might have to use postfix `-mt` to link to these libraries. +Note: added `-lboost_filesystem` for the default_resource example, and `-lboost_thread` to make the json-example thread safe. Also added `-lboost_coroutine -lboost_context` to make synchronous flushing of response stream work. On some systems you might have to use postfix `-mt` to link to these libraries. You can now also compile using CMake and make: diff --git a/server_http.hpp b/server_http.hpp index 71fc8c9..f305ee9 100644 --- a/server_http.hpp +++ b/server_http.hpp @@ -25,64 +25,19 @@ namespace SimpleWeb { std::shared_ptr socket; - std::shared_ptr async_timer; - - std::shared_ptr async_writing; - std::shared_ptr async_waiting; - Response(boost::asio::io_service& io_service, std::shared_ptr socket, std::shared_ptr strand, - boost::asio::yield_context& yield): - strand(strand), yield(yield), socket(socket), async_timer(new boost::asio::deadline_timer(io_service)), - async_writing(new bool(false)), async_waiting(new bool(false)), stream(&streambuf) {} - - void async_flush(std::function callback=nullptr) { - if(!callback && !socket->lowest_layer().is_open()) { - if(*async_waiting) - async_timer->cancel(); - throw std::runtime_error("Broken pipe."); - } - - std::shared_ptr write_buffer(new boost::asio::streambuf); - std::ostream response(write_buffer.get()); - response << stream.rdbuf(); - - //Wait until previous async_flush is finished - strand->dispatch([this](){ - if(*async_writing) { - *async_waiting=true; - try { - async_timer->async_wait(yield); - } - catch(std::exception& e) { - } - *async_waiting=false; - } - }); - - *async_writing=true; - - auto socket_=this->socket; - auto async_writing_=this->async_writing; - auto async_timer_=this->async_timer; - auto async_waiting_=this->async_waiting; - - boost::asio::async_write(*socket, *write_buffer, - strand->wrap([socket_, write_buffer, callback, async_writing_, async_timer_, async_waiting_] - (const boost::system::error_code& ec, size_t /*bytes_transferred*/) { - *async_writing_=false; - if(*async_waiting_) - async_timer_->cancel(); - if(callback) - callback(ec); - })); - } + boost::asio::yield_context& yield): strand(strand), yield(yield), socket(socket), stream(&streambuf) {} void flush() { boost::asio::streambuf write_buffer; std::ostream response(&write_buffer); response << stream.rdbuf(); - boost::asio::async_write(*socket, write_buffer, yield); + boost::system::error_code ec; + boost::asio::async_write(*socket, write_buffer, yield[ec]); + + if(ec) + throw std::runtime_error(ec.message()); } public: @@ -103,12 +58,7 @@ namespace SimpleWeb { return manip(*this); } }; - - static Response& async_flush(Response& r) { - r.async_flush(); - return r; - } - + static Response& flush(Response& r) { r.flush(); return r; @@ -355,16 +305,20 @@ namespace SimpleWeb { try { resource_function(response, request); } - catch(std::exception& e) { + catch(const std::exception& e) { return; } - response.async_flush([this, socket, request, timer](const boost::system::error_code& ec) { - if(timeout_content>0) - timer->cancel(); - if(!ec && stof(request->http_version)>1.05) - read_request_and_content(socket); - }); + try { + response.flush(); + } + catch(const std::exception &e) { + return; + } + if(timeout_content>0) + timer->cancel(); + if(stof(request->http_version)>1.05) + read_request_and_content(socket); }); } };