diff --git a/include/server/connection.hpp b/include/server/connection.hpp index 08821597e..ea4e7f81e 100644 --- a/include/server/connection.hpp +++ b/include/server/connection.hpp @@ -65,6 +65,9 @@ class Connection : public std::enable_shared_from_this std::vector compressed_output; // Header compression_header; std::vector output_buffer; + //Keep alive support + bool keep_alive = false; + short processed_requests = 512; }; } } diff --git a/src/server/connection.cpp b/src/server/connection.cpp index 9cb478afc..4b1cdd518 100644 --- a/src/server/connection.cpp +++ b/src/server/connection.cpp @@ -4,12 +4,14 @@ #include #include +#include #include #include #include #include #include +#include namespace osrm { @@ -26,12 +28,12 @@ boost::asio::ip::tcp::socket &Connection::socket() { return TCP_socket; } /// Start the first asynchronous operation for the connection. void Connection::start() { - TCP_socket.async_read_some( - boost::asio::buffer(incoming_data_buffer), - strand.wrap(boost::bind(&Connection::handle_read, - this->shared_from_this(), - boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred))); + TCP_socket.async_read_some( + boost::asio::buffer(incoming_data_buffer), + strand.wrap(boost::bind(&Connection::handle_read, + this->shared_from_this(), + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred))); } void Connection::handle_read(const boost::system::error_code &error, std::size_t bytes_transferred) @@ -45,9 +47,9 @@ void Connection::handle_read(const boost::system::error_code &error, std::size_t http::compression_type compression_type(http::no_compression); RequestParser::RequestStatus result; std::tie(result, compression_type) = - request_parser.parse(current_request, - incoming_data_buffer.data(), - incoming_data_buffer.data() + bytes_transferred); + request_parser.parse(current_request, + incoming_data_buffer.data(), + incoming_data_buffer.data() + bytes_transferred); // the request has been parsed if (result == RequestParser::RequestStatus::valid) @@ -55,32 +57,40 @@ void Connection::handle_read(const boost::system::error_code &error, std::size_t current_request.endpoint = TCP_socket.remote_endpoint().address(); request_handler.HandleRequest(current_request, current_reply); + if (boost::iequals(current_request.connection, "close")) { + current_reply.headers.emplace_back("Connection", "close"); + } else { + keep_alive = true; + current_reply.headers.emplace_back("Connection", "keep-alive"); + current_reply.headers.emplace_back("Keep-Alive", "timeout=5, max=512"); + } + // compress the result w/ gzip/deflate if requested switch (compression_type) { - case http::deflate_rfc1951: - // use deflate for compression - current_reply.headers.insert(current_reply.headers.begin(), - {"Content-Encoding", "deflate"}); - compressed_output = compress_buffers(current_reply.content, compression_type); - current_reply.set_size(static_cast(compressed_output.size())); - output_buffer = current_reply.headers_to_buffers(); - output_buffer.push_back(boost::asio::buffer(compressed_output)); - break; - case http::gzip_rfc1952: - // use gzip for compression - current_reply.headers.insert(current_reply.headers.begin(), - {"Content-Encoding", "gzip"}); - compressed_output = compress_buffers(current_reply.content, compression_type); - current_reply.set_size(static_cast(compressed_output.size())); - output_buffer = current_reply.headers_to_buffers(); - output_buffer.push_back(boost::asio::buffer(compressed_output)); - break; - case http::no_compression: - // don't use any compression - current_reply.set_uncompressed_size(); - output_buffer = current_reply.to_buffers(); - break; + case http::deflate_rfc1951: + // use deflate for compression + current_reply.headers.insert(current_reply.headers.begin(), + {"Content-Encoding", "deflate"}); + compressed_output = compress_buffers(current_reply.content, compression_type); + current_reply.set_size(static_cast(compressed_output.size())); + output_buffer = current_reply.headers_to_buffers(); + output_buffer.push_back(boost::asio::buffer(compressed_output)); + break; + case http::gzip_rfc1952: + // use gzip for compression + current_reply.headers.insert(current_reply.headers.begin(), + {"Content-Encoding", "gzip"}); + compressed_output = compress_buffers(current_reply.content, compression_type); + current_reply.set_size(static_cast(compressed_output.size())); + output_buffer = current_reply.headers_to_buffers(); + output_buffer.push_back(boost::asio::buffer(compressed_output)); + break; + case http::no_compression: + // don't use any compression + current_reply.set_uncompressed_size(); + output_buffer = current_reply.to_buffers(); + break; } // write result to stream boost::asio::async_write(TCP_socket, @@ -103,11 +113,11 @@ void Connection::handle_read(const boost::system::error_code &error, std::size_t { // we don't have a result yet, so continue reading TCP_socket.async_read_some( - boost::asio::buffer(incoming_data_buffer), - strand.wrap(boost::bind(&Connection::handle_read, - this->shared_from_this(), - boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred))); + boost::asio::buffer(incoming_data_buffer), + strand.wrap(boost::bind(&Connection::handle_read, + this->shared_from_this(), + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred))); } } @@ -116,9 +126,16 @@ void Connection::handle_write(const boost::system::error_code &error) { if (!error) { - // Initiate graceful connection closure. - boost::system::error_code ignore_error; - TCP_socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignore_error); + if (keep_alive && processed_requests > 0) { + --processed_requests; + current_request = http::request(); + request_parser = RequestParser(); + this->start(); + } else { + // Initiate graceful connection closure. + boost::system::error_code ignore_error; + TCP_socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignore_error); + } } } diff --git a/src/server/http/reply.cpp b/src/server/http/reply.cpp index d279417e0..b73e381a7 100644 --- a/src/server/http/reply.cpp +++ b/src/server/http/reply.cpp @@ -103,11 +103,7 @@ boost::asio::const_buffer reply::status_to_buffer(const reply::status_type statu return boost::asio::buffer(http_bad_request_string); } -reply::reply() : status(ok) -{ - // We do not currently support keep alive. Always set 'Connection: close'. - headers.emplace_back("Connection", "close"); -} +reply::reply() : status(ok) {} } } }